java使用condition进行线程通信

来源:互联网 发布:淘宝网店图标尺寸 编辑:程序博客网 时间:2024/06/05 20:57


package cond;import java.util.concurrent.*;import java.util.concurrent.locks.*; public class Account{// 显式定义Lock对象private final Lock lock = new ReentrantLock();// 获得指定Lock对象对应的Conditionprivate final Condition cond  = lock.newCondition();// 封装账户编号、账户余额的两个成员变量private String accountNo;private double balance;// 标识账户中是否已有存款的旗标private boolean flag = false;public Account(){}// 构造器public Account(String accountNo , double balance){this.accountNo = accountNo;this.balance = balance;}// accountNo的setter和getter方法public void setAccountNo(String accountNo){this.accountNo = accountNo;}public String getAccountNo(){return this.accountNo;}// 因此账户余额不允许随便修改,所以只为balance提供getter方法,public double getBalance(){return this.balance;}public void draw(double drawAmount){// 加锁lock.lock();try{// 如果flag为假,表明账户中还没有人存钱进去,取钱方法阻塞if (!flag){cond.await();}else{// 执行取钱System.out.println(Thread.currentThread().getName()+ " 取钱:" +  drawAmount);balance -= drawAmount;System.out.println("账户余额为:" + balance);// 将标识账户是否已有存款的旗标设为false。flag = false;// 唤醒其他线程cond.signalAll();}}catch (InterruptedException ex){ex.printStackTrace();}// 使用finally块来释放锁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块来释放锁finally{lock.unlock();}}// 下面两个方法根据accountNo来重写hashCode()和equals()方法public int hashCode(){return accountNo.hashCode();}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;}}


package cond; 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;}// 重复100次执行存款操作public void run(){for (int i = 0 ; i < 100 ; i++ ){account.deposit(depositAmount);}}}

package cond; 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;}// 重复100次执行取钱操作public void run(){for (int i = 0 ; i < 100 ; i++ ){account.draw(drawAmount);}}}


package cond; public class DrawTest{public static void main(String[] args){// 创建一个账户Account acct = new Account("1234567" , 0);new DrawThread("取钱者" , acct , 800).start();new DepositThread("存款者甲" , acct , 800).start();new DepositThread("存款者乙" , acct , 800).start();new DepositThread("存款者丙" , acct , 800).start();}}

账户余额为:0.0
存款者乙 存款:800.0
账户余额为:800.0
取钱者 取钱:800.0
账户余额为:0.0
存款者乙 存款:800.0
账户余额为:800.0
取钱者 取钱:800.0
账户余额为:0.0
存款者乙 存款:800.0
账户余额为:800.0