wait(): 使当前线程等待,直到其他线程调用该同步监视器notify()方法 , 或者notifyAll()方法来唤醒该线程。
wai()方法有三种形式 , 无参的一直等 ;带毫秒的 , 和带微秒的会等待指定时间后自动苏醒。
调用wait()方法的当前线程会释放该同步监视器的锁定
notify(): 唤醒在同步监视器上等待的单个线程,如果所有线程都在此同步监视器上等待,则唤醒其中任意一个。
只有当前线程放弃对该同步监视器的锁定后(使用wait()方法),才能执行被唤醒的线程
notifyAll(): 唤醒在此同步监视器上等待的所有线程,只有当前线程放弃对同步监视器的锁定后才可以执行被唤醒的线程
demo:存钱和取钱:
存款和取款不断的重复存与取得动作
存款者存了钱, 取款者就立即去取
不允许存款者连续存两次 , 不允许取款者连续取两次
public class Account { private String account;//账户 private double balance;//余额 private boolean flag = false; //标识是否已有存款 , 有为true public Account() { super(); // TODO Auto-generated constructor stub } public Account(String account, double balance) { super(); this.account = account; this.balance = balance; } //账户余额不允许随便修改 , 只提供getter方法 public double getBalance() { return balance; } //取款 public synchronized void draw(double drawMoney) { try { if(!flag) {//false说明没得存款 , 那就等待 咯 wait(); }else { System.out.println(Thread.currentThread().getName() + "取钱:" + drawMoney); //true 执行取钱的操作 balance -= drawMoney; System.out.println("账户余额为:" + balance); //取完钱 , 改flag flag = false; //唤醒其他线程 notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } //存钱 public synchronized void save(double saveMoney) { try { if(flag) {//true 标识有人存钱了 , 存钱方法阻塞 wait(); } else { // false 没钱 , 开始存钱 System.out.println(Thread.currentThread().getName() + "存款:" + saveMoney); balance += saveMoney; System.out.println("账户余额为:" + balance); //存完钱 , 改flag flag = true; //唤醒其他线程 notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } }
public class DrawThread extends Thread{ private Account account;//账号 private double drawMoney;//想要划扣的钱 public DrawThread(String name , Account account, double drawMoney) { super(name); this.account = account; this.drawMoney = drawMoney; } public void run() { for(int i = 0 ; i < 100; i++) {//重复执行取钱的操作 account.draw(drawMoney); } } }
public class SaveThread extends Thread{ private Account account;//账号 private double saveMoney;//想要存的钱 public SaveThread(String name , Account account , double saveMoney) { super(name); this.account = account; this.saveMoney = saveMoney; } public void run() { //重复执行存钱的操作 for(int i = 0 ; i < 100 ; i++) { account.save(saveMoney); } } }
public class Test { public static void main(String[] args) { Account account = new Account("123456",0); new DrawThread("取钱者:", account, 500).start(); new SaveThread("存钱者-A", account, 500).start(); new SaveThread("存钱者-B", account, 500).start(); new SaveThread("存钱者-C", account, 500).start(); } }