java编程多线程并发处理实例解析
本文主要是通过一个银行用户取钱的实例,演示java编程多线程并发处理场景,具体如下。
从一个例子入手:实现一个银行账户取钱场景的实例代码。
第一个类:Account.java
账户类:
packagecn.edu.byr.test;
publicclassAccount{
privateStringaccountNo;
privatedoublebalance;
publicAccount(){
}
publicAccount(StringaccountNo,doublebalance){
this.accountNo=accountNo;
this.balance=balance;
}
publicinthashcode(){
returnaccountNo.hashCode();
}
publicStringgetAccountNo(){
returnthis.accountNo;
}
publicdoublegetBalance(){
returnthis.balance;
}
publicvoidsetBalance(doublebalance){
this.balance=balance;
}
publicBooleanequals(Objectobj){
if(this==obj)
returntrue;
if(obj!=null&&obj.getClass()==Account.class){
Accounttarget=(Account)obj;
returntarget.getAccountNo().equals(accountNo);
}
returnfalse;
}
}
第二个类:DrawThread.java
取钱线程类:
packagecn.edu.byr.test;
publicclassDrawThreadextendsThread{
privateAccountaccount;
privatedoubledrawAmount;
publicDrawThread(Stringname,Accountaccount,doubledrawAmount){
super(name);
this.account=account;
this.drawAmount=drawAmount;
}
publicvoidrun(){
//synchronized(account){
if(account.getBalance()>drawAmount){
System.out.println(getName()+"取钱成功,吐出钞票:"+drawAmount);
//try{
//Thread.sleep(1);
//}
//catch(InterruptedExceptione){
//e.printStackTrace();
//}
account.setBalance(account.getBalance()-drawAmount);
System.out.println("\t余额为:"+account.getBalance());
}else
System.out.println(getName()+"取钱失败,余额不足!");
//}
}
publicstaticvoidmain(String[]args){
Accountacct=newAccount("123456",1000);
newDrawThread("A",acct,800).start();
newDrawThread("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编程多线程并发处理实例解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!