线程同步:银行帐户存、取款问题

来源:互联网 发布:易学大师宝宝取名软件 编辑:程序博客网 时间:2024/05/05 08:41

1.银行账户类

package com.bankAccount.test;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Account {//显式定义Lock对象private final Lock lock=new ReentrantLock(); //获得指定Lock对象对应的Conditionprivate final Condition cond=lock.newCondition();//封装账户编号,账户余额的两个成员变量private String accoutNo;private double balance;//标识账户中是否已有存款的旗标private boolean flag=false;public Account(){}//构造器public Account(String accountNo,double balance){this.accoutNo=accountNo;this.balance=balance;}public String getAccoutNo() {return accoutNo;}public void setAccoutNo(String accoutNo) {this.accoutNo = accoutNo;}//因为账户余额不可以随便修改,所以只为balance提供getter方法public double getBalance() {return this.balance;}public void draw(double drawAmount){//加锁lock.lock();try{if(!flag){cond.await();}else{//执行取钱操作System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);balance-=drawAmount;System.out.println("账户余额为:"+balance);//将标识账户是否已有存款的旗标设为falseflag=false;//唤醒其他进程cond.signalAll();}}catch(InterruptedException ex){ex.printStackTrace();}finally{lock.unlock();}}public void deposit(double depositAmount){lock.lock();try{//如果flag为真,表明账户中已经有人存钱进去,存钱方法阻塞if(flag){cond.await();}else{//执行存款操作System.out.println(Thread.currentThread().getName()+"存款:"+depositAmount);balance+=depositAmount;System.out.println("账户余额为:"+balance);//将表示是否已有存款的旗标设为trueflag=true;//唤醒其他线程cond.signalAll();}}catch(InterruptedException ex){ex.printStackTrace();}finally{lock.unlock();}}public int hashCode(){return accoutNo.hashCode();}public boolean equals(Object obj){if(this==obj)return true;if(obj!=null&&obj.getClass()==Account.class){Account target=(Account)obj;return target.getAccoutNo().equals(accoutNo);}return false;}}

2.存款线程

package com.bankAccount.test;public class DepositThread extends Thread{private Account account;//当前存款线程所希望存的钱数private double depositAmount;public DepositThread(String name,Account account,double depositAmount){super(name);this.account=account;this.depositAmount=depositAmount;}public void run(){for(int i=0;i<100;i++){account.deposit(depositAmount);}}}

3.取款线程

package com.bankAccount.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(){//使用account作为同步监视器,任何线程进入下面同步代码块之前//必须先获得对account账户的锁定---其他线程无法获得锁,也就无法修改它//该做法符合:"加锁->修改->释放锁"for(int i=0;i<100;i++){account.draw(drawAmount);}}}
4.测试类

package com.bankAccount.test;public class DrawTest {public static void main(String[] args) {//创建一个账户Account acct=new Account("123",0);//模拟两个线程对同一个账户取 钱new DrawThread("取钱者",acct,800).start();new DepositThread("存款者甲",acct,800).start();new DepositThread("存款者乙",acct,800).start();new DepositThread("存款者丙",acct,800).start();}}

结果:














































0 0
原创粉丝点击