欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java编程多线程并发处理实例解析

程序员文章站 2023-12-01 09:47:28
本文主要是通过一个银行用户取钱的实例,演示java编程多线程并发处理场景,具体如下。 从一个例子入手:实现一个银行账户取钱场景的实例代码。 第一个类:account...

本文主要是通过一个银行用户取钱的实例,演示java编程多线程并发处理场景,具体如下。

从一个例子入手:实现一个银行账户取钱场景的实例代码。

第一个类:account.java

账户类:

package cn.edu.byr.test;
public class account {
	private string accountno;
	private double balance;
	public account(){
	}
	public account(string accountno,double balance){
		this.accountno = accountno;
		this.balance = balance;
	}
	public int hashcode(){
		return accountno.hashcode();
	}
	public string getaccountno(){
		return this.accountno;
	}
	public double getbalance(){
		return this.balance;
	}
	public void setbalance(double balance){
		this.balance = balance;
	}
	public boolean equals(object obj){
		if(this == obj) 
		      return true;
		if(obj != null && obj.getclass() == account.class){
			account target = (account)obj;
			return target.getaccountno().equals(accountno);
		}
		return false;
	}
}

第二个类:drawthread.java

取钱线程类:

package cn.edu.byr.test;
public class drawthread extends thread {
	private account account;
	private double drawamount;
	public drawthread(string name,account account,double drawamount){
		super(name);
		this.account = account;
		this.drawamount = drawamount;
	}
	public void run(){
		//   synchronized (account) { 
		if(account.getbalance() > drawamount){
			system.out.println(getname() + "取钱成功,吐出钞票:" + drawamount);
			//       try{ 
			//         thread.sleep(1); 
			//       } 
			//       catch(interruptedexception e){ 
			//         e.printstacktrace(); 
			//       } 
			account.setbalance(account.getbalance() - drawamount);
			system.out.println("\t 余额为 : " + account.getbalance());
		} else 
		        system.out.println(getname() + "取钱失败,余额不足!");
		//   }
	}
	public static void main(string[] args){
		account acct = new account("123456",1000);
		new drawthread("a",acct,800).start();
		new drawthread("b",acct,800).start();
	}
}

上面代码中注释掉的部分:(1)synchronized同步代码块 (2)线程休眠。如果注释掉(1)、(2),则运行结果有多种可能性,可能性之一(概率较小),符合正常逻辑:

b取钱成功,吐出钞票:800.0
余额为 : 200.0
a取钱失败,余额不足!

应该是b先强找到取钱资源,并且正确修改余额后,a才开始判断用户余额;这种概率非常小,多数运行会类似以下情况:

a取钱成功,吐出钞票:800.0
b取钱成功,吐出钞票:800.0
余额为 : -600.0
余额为 : 200.0

这明显是不符合逻辑的,从运行结果可以猜测,a先抢占资源,取出金额,但在修改余额之前,资源被b抢占;由于余额未被修改,则b看到余额仍然是800,b仍然取出金额;a先运行修改余额,但并未打印,b抢夺资源;b修改余额,并打印余额,为-600;a打印余额,为200;

如果加上(2)线程休眠,则一定是错误状况,因为a或b在取出金额后一定会因为sleep释放cpu资源,jvm会调用其他处于准备状态的进程。第二个取钱判断余额一定是错误的。

如果加上(1)synchronized同步代码块,在线程run方法体中对account进行加锁;则每次都会保证执行逻辑正常:

a取钱成功,吐出钞票:800.0
余额为 : 200.0
b取钱失败,余额不足!
可以设想一下执行过程:

a先抢占资源,在run方法体初始对account类进行加锁;然后开始执行同步代码块;如果执行到中间某个环节,cpu资源被b抢占;b开始执行,一开始也会对account类进行加锁。但是加锁时会发现account已经被a占用,则会调整为阻塞状态等待a释放资源;a执行完同步代码块后释放account的锁,b继续执行;b运行时看到的余额保证是a已经修改过的,会按照正确逻辑正常执行。

总结

以上就是本文关于java编程多线程并发处理实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!