Day08_05目标:线程通信

目标:线程通信

线程通信:

多个线程因为在同一个进程中,所以互相通信比较容易的。

线程通信的经典模型:

生产者与消费者问题。
生产者负责生成商品,消费者负责消费商品。
生产不能过剩,消费不能没有。

​ 厂家 口红 消费者。

模拟一个案例:

​ 小明和小红有一个共同账户:共享资源
​ 他们有3个爸爸(亲爸,岳父,干爹)给他们存钱。

​ 模型:小明和小红去取钱,如果有钱就取出,然后等待自己,唤醒他们3个爸爸们来存钱
​ 他们的爸爸们来存钱,如果发现有钱就不存,没钱就存钱,然后等待自己,唤醒孩子们来取钱。
​ 做整存整取:10000元。
分析:
​ 生产者线程:亲爸,岳父,干爹
​ 消费者线程:小明,小红
​ 共享资源:账户对象。

注意:线程通信一定是多个线程在操作同一个资源才需要进行通信。
线程通信必须先保证线程安全,否则毫无意义,代码也会报错!

线程通信的核心方法:
public void wait(): 让当前线程进入到等待状态 此方法必须锁对象调用.
public void notify() : 唤醒当前锁对象上等待状态的某个线程 此方法必须锁对象调用
public void notifyAll() : 唤醒当前锁对象上等待状态的全部线程 此方法必须锁对象调用

public class ThreadCommunication {
    public static void main(String[] args) {
        // 1.创建1个账户对象。
        Account acc = new Account(0 , "ICBC-111");

        // 2.创建消费者线程:小明/小红  取钱
        new DrawThread(acc,"小明").start();
        new DrawThread(acc,"小红").start();

        // 3.创建生产者线程:亲爸,岳父,干爹
        new SaveThread(acc,"亲爸").start();
        new SaveThread(acc,"岳父").start();
        new SaveThread(acc,"干爹").start();
    }
}

账户类

public class Account {
    private double money ; // 余额
    private String cardId ;
    // 创建一把锁对象
    private final Lock lock = new ReentrantLock();
    public Account(){

    }
    public Account(double money, String cardId) {
        this.money = money;
        this.cardId = cardId;
    }
    // 亲爸,干爹,岳父
    public synchronized void saveMoney(double money) {
        try{
            String name = Thread.currentThread().getName();
            if(this.money > 0){
                // 有钱,不需要存钱
                this.notifyAll(); // 唤醒别人
                this.wait();// 等待自己,释放锁!
            }else{
                // 没钱
                this.money += money;
                System.out.println(name+"来存钱,存钱后剩余:"+this.money);
                this.notifyAll(); // 唤醒别人
                this.wait();// 等待自己,释放锁!
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 小明,小红
    public synchronized void drawMoney(double money) {
       try{
           String name = Thread.currentThread().getName();
           if(this.money >= money){
                // 余额足够
               this.money -= money;
               System.out.println(name+"来取钱"+money+"成功!剩余:"+ this.money);
               // 取完钱后,等待自己,唤醒别人
               this.notifyAll(); // 唤醒别人
               this.wait();// 等待自己,释放锁!
           }else{
               // 余额不足。
               this.notifyAll(); // 唤醒别人
               this.wait();// 等待自己,释放锁!
           }
       }catch (Exception e){
           e.printStackTrace();
       }
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

}

存钱的线程类。

public class SaveThread extends Thread {
    private Account acc ;
    public SaveThread(Account acc , String name){
        super(name);
        this.acc = acc;
    }
    @Override
    public void run() {
        // 亲爸,干爹,岳父
        while(true){
            acc.saveMoney(10000);
        }
    }
}

取钱的线程类

public class DrawThread extends Thread {
    private Account acc ;
    public DrawThread(Account acc , String name){
        super(name);
        this.acc = acc;
    }
    @Override
    public void run() {
        while(true){
            // 小明 小红
            acc.drawMoney(10000);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值