美文网首页
java多线程之线程间的通信(wait,notify)

java多线程之线程间的通信(wait,notify)

作者: 不二不二熊 | 来源:发表于2019-09-28 22:15 被阅读0次
    一、入门demo,实现经典的生产者消费者模型
    • 消费者
    /**
     * @author: localhost
     * @program: mySpringBoot
     * @description: 消费者
     * @create: 2019-09-06 13:16
     **/
    @Slf4j
    public class ConsumerRunabble implements Runnable {
        private List<Integer> list;
    
        public ConsumerRunabble(List<Integer> list) {
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true) {
                synchronized (list) {
                    if (list.size() <=0) {
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("===消费者收到通知,开始消费数据===");
                    Iterator<Integer> iterator = list.iterator();
                    while (iterator.hasNext()) {
                        Integer next = iterator.next();
                        if (next != null) {
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            log.info("消费了数据:{}", next);
                            iterator.remove();
                        }
                    }
                    System.out.println("====数据消费完毕,通知生产者生产数据==");
                    list.notifyAll();
                }
            }
        }
    }
    
    • 生产者
    /**
     * @author: localhost
     * @program: mySpringBoot
     * @description: 生产者
     * @create: 2019-09-06 13:23
     **/
    @Slf4j
    public class ProducerRunabble implements Runnable {
        private List<Integer> list;
    
        public ProducerRunabble(List<Integer> list) {
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true) {
                synchronized (list) {
                    if (list.size() > 0) {
                        try {
                            list.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //开始生产数据
                    System.out.println("======收到通知,开始生产数据======");
                    for (int i = 0; i < 3; i++) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        list.add(i);
                        log.info("生产者添加了数据:{}", i);
                    }
                    list.notifyAll();
                    System.out.println("====数据生产完毕,通知消费者消费数据===");
                }
            }
        }
    }
    
    • 测试类
    /**
     * @author: localhost
     * @program: mySpringBoot
     * @description:
     * @create: 2019-09-06 13:29
     **/
    public class TestDemo {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            //推荐使用线程池创建,模拟测试暂时手动创建
            new Thread(new ProducerRunabble(list)).start();
            new Thread(new ConsumerRunabble(list)).start();
        }
    }
    
    • 输出
      控制台打印结果
    二、关于通知等待机制

    其实可以类比为人类世界的去医院排队挂号验血,首先你要去排队,然后等待,当有人通知你可以进行验血的时候你才去启动,其他时间都是等待状态。与sleep()不同的是,wait()会释放持有的锁。当被唤醒时,会重新去获取锁,但是不一定能马上获取到,这取决于cpu的分配。

    另外,我强烈建议你在唤醒队列的时候,使用notifyAll()而不是notify()。打个比方,假设等待队列中有两个等待线程a和线程b,此时你需要唤醒线程b,使用notify()结果却唤醒了a线程,这是不值当的。

    因为Java给我们提供了等待唤醒机制,因此在实际工作中们,对于某些使用轮询的地方,我们不妨将他替换成等待唤醒,这样可以节省资源。

    相关文章

      网友评论

          本文标题:java多线程之线程间的通信(wait,notify)

          本文链接:https://www.haomeiwen.com/subject/udgsyctx.html