展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

线程间通讯

wait、notify、notifyAll

  • 简介
1、在多线程环境下,有时候一个线程的执行,依赖于另外一个线程的某种状态的改变,这个时候,我们就可以使用wait与notify或者notifyAll
2、wait跟sleep的区别:wait会释放持有的锁,而sleep不会,sleep只是让线程在指定的时间内,不去抢占cpu的资源 
3、注意点:wait notify必须放在同步代码块中, 且必须拥有当前对象的锁,即不能取得A对象的锁,而调用B对象的wait 哪个对象wait,就得调哪个对象的notify
4、notify跟notifyAll的区别:nofity随机唤醒一个等待的线程 notifyAll唤醒所有在该对象上等待的线程
  • 案例1
public class Demo {

    private static volatile boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        // 线程1,while循环中的参数一直为false,需要等线程2先执行完
        new Thread(()->{
            while (!flag) {
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("flag is false");
            }
            System.out.println("flag is true");
        }).start();

        // 休眠
        Thread.sleep(1000L);

        // 线程2,将flag设置为true,线程1需要等待线程2执行完
        new Thread(()->{
            flag = true;
        }).start();
    }

}

# 控制台结果:
flag is false
flag is true
  • 案例2
public class Demo1 {

    private static volatile boolean flag = false;

    public static void main(String[] args) throws InterruptedException {

        Object obj = new Object();

        new Thread(()->{
            while (!flag) {    // 为true
                synchronized (obj) {        // 获取锁
                    try {
                        System.out.println("flag is false");     // (1)
                        obj.wait();     // 挂起线程
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            System.out.println("flag is true");     // (3)
        }).start();

        new Thread(()->{
            while (!flag) {
                synchronized (obj) {
                    try {
                        System.out.println("flag is false");     // (2)
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            System.out.println("flag is true");     // (4)
        }).start();

        // 休眠1秒
        Thread.sleep(1000L);

        new Thread(()->{
            flag = true;
            synchronized (obj) {
                obj.notifyAll();        // 唤醒所有等待的线程
            }
        }).start();
    }

}

# 控制台
flag is false
flag is false
flag is true
flag is true

等待通知经典模型之生产者消费者

  • 代码案例
# 中间商
public class Medium {

    private int num = 0;
    // 库存量
    private static final int TOTAL = 20;

    /**
     * 接收生产数据
     */
    public synchronized void put() {
        //判断当前的库存,是否已经是最大的库存容量
        if (num < TOTAL) {
            //如果不是,生产完成之后,通知消费者进行消费
            System.out.println("新增库存-------->当前库存" + ++num);
            try {
                Thread.sleep(500L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            notifyAll();        // 唤醒所有等待线程
        } else {
            //如果是,则通知生产者进行等待
            try {
                System.out.println("新增库存---------> 库存已满"+num);
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取消费数据
     */
    public synchronized void take() {
        //判断当前库存是否不足
        if (num > 0) {
            //如果充足,在消费完成之后通知生产者进行生产
            System.out.println("消费库存-----------> 当前库存容量" + --num);
            try {
                Thread.sleep(1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            notifyAll();
        } else {
            //如果不足,通知消费者暂停消费
            System.out.println("消费库存-----------> 库存不足"+num);
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

# 生产者
public class Producer implements Runnable {

    private Medium medium;

    public Producer(Medium medium) {
        this.medium = medium;
    }

    @Override
    public void run() {
        while (true) {
            medium.put();
        }
    }

}

# 消费者
public class Consumer implements Runnable{

    private Medium medium;

    public Consumer(Medium medium) {
        this.medium = medium;
    }

    @Override
    public void run() {
        while (true) {
            medium.take();
        }
    }

}

# 测试类
public class Main {

    public static void main(String[] args) {
        Medium medium = new Medium();
        // new 3个消费者
        new Thread(new Consumer(medium)).start();
        new Thread(new Consumer(medium)).start();
        new Thread(new Consumer(medium)).start();
        // new 5个生产者
        new Thread(new Producer(medium)).start();
        new Thread(new Producer(medium)).start();
        new Thread(new Producer(medium)).start();
        new Thread(new Producer(medium)).start();
        new Thread(new Producer(medium)).start();
    }

}
posted @ 2022-05-14 21:46  DogLeftover  阅读(14)  评论(0编辑  收藏  举报