可以使用wait(),nitify(),notifyAll()来进行线程协作,这三个方法必须由同步监视器来调用。
下列定义一个Account类。该类存、取钱交替进行。
public class Account { private String accountNo; private double balance; private boolean flag = false; public Account() {} public Account(String accountNo, double balance) { this.accountNo = accountNo; this.balance = balance; } public String getAccountNo() { return this.accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public double getBalance() { return this.balance; } public synchronized void draw(double drawAmount) { try{ if(!flag) { wait(); } else { System.out.println(Thread.currentThread().getName() + "draw" + drawAmount); flag = false; notifyAll(); } } catch( InterruptedException e) { e.printStackTrace(); } } public synchronized void deposit(double depositAmount) { try { if(flag) { wait(); } else { System.out.println(Thread.currentThread().getName() + "deposit" + depositAmount); flag = true; notifyAll(); } } catch(InterruptedException e) { e.printStackTrace(); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((accountNo == null) ? 0 : accountNo.hashCode()); long temp; temp = Double.doubleToLongBits(balance); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + (flag ? 1231 : 1237); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Account other = (Account) obj; if (accountNo == null) { if (other.accountNo != null) return false; } else if (!accountNo.equals(other.accountNo)) return false; if (Double.doubleToLongBits(balance) != Double .doubleToLongBits(other.balance)) return false; if (flag != other.flag) return false; return true; } }
每个存、取线程会分别执行100次存取款操作。
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() { for (int i = 0; i < 100; i++) { account.draw(drawAmount); } } } 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); } } }
下面执行一个测试类,看看效果。最后程序会阻塞,原因是取款线程100次取款操作执行完了,而取款者的线程还没有执行完取款操作,在一直等待被唤醒。
public class DrawTest { public static void main(String[] args) { Account account = new Account("wz123", 0); new DrawThread("drawer ", account, 800).start(); new DepositThread("depositor A ", account, 800).start(); new DepositThread("depositor B ", account, 800).start(); new DepositThread("depositor C ", account, 800).start(); } }