java 多线程 8 : 线程通信

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();
    }
}

温故而知新
原文地址:https://www.cnblogs.com/Uzai/p/9679988.html