zoukankan      html  css  js  c++  java
  • 通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll

    wait(),notify()和notifyAll()都是Java基类java.lang.Object的方法。

    通俗解释
    wait():在当前线程等待其它线程唤醒。
    notify(): 唤醒一个线程正在等待这个对象的监视器。
    notifyAll(): 唤醒在这个对象监视器上等待的所有线程。
    这三个方法,都是Java语言提供的实现线程间阻塞(Blocking)和控制进程内调度(inter-process communication)的底层机制。
    下面通过一个生产者/消费者的例子来讲解这三个方法的使用

    /**
     * 消费者
     * Created by Wiki on 16/1/28.
     */
    public class Customer implements Runnable {
        private String name;
        private Channel channel;
    
        public Customer(String name, Channel channel) {
            this.name = name;
            this.channel = channel;
        }
    
        @Override
        public void run() {
            while (true) {
                Good good = channel.get();
                if (good != null) {
                    System.out.println(name + " 获得商品:" + good.getName());
                } else {
                    synchronized (channel) {
                        try {
                            System.out.println(name + " 进入等待");
                            channel.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
    /**
     * 生产者
     * Created by Wiki on 16/1/28.
     */
    public class Producer implements Runnable {
        private static volatile int goodNumber = 0;
    
        private String name;
        private Channel channel;
    
        public Producer(String name, Channel channel) {
            this.name = name;
            this.channel = channel;
        }
    
        @Override
        public void run() {
            while (true) {
                int sleep = new Random().nextInt(2000);
                try {
                    Thread.sleep(sleep);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Good good = new Good("商品-编号" + (++goodNumber));
                System.out.println(name + " 生产商品:" + good.getName());
                channel.put(good);
            }
        }
    }
    /**
     * 商品
     * Created by Wiki on 16/1/28.
     */
    public class Good {
        private String name;
    
        public Good(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    /**
     * 消费通道
     * Created by Wiki on 16/1/28.
     */
    public class Channel {
        private Queue<Good> goodList = new LinkedList<>();
    
        public synchronized Good get() {
            if (goodList.size() == 0) {
                return null;
            }
            Good good = goodList.remove();
            return good;
        }
    
        public synchronized void put(Good good) {
            goodList.add(good);
    //        notifyAll();
            notify();
        }
    }
    public class Main {
    
        public static void main(String[] args) {
            Channel channel = new Channel();
            new Thread(new Producer("生产者1", channel)).start();
            new Thread(new Producer("生产者2", channel)).start();
            new Thread(new Producer("生产者2", channel)).start();
    
            new Thread(new Customer("消费者1", channel)).start();
            new Thread(new Customer("消费者2", channel)).start();
            new Thread(new Customer("消费者3", channel)).start();
        }
    }

    运行结果分析一(notify):

    每次生产一个商品调用notify时,都只唤醒一个消费者进行消费,唤醒原则是从等待时间最长的开始。

    消费者1 进入等待
    消费者2 进入等待
    消费者3 进入等待
    生产者1 生产商品:商品-编号1
    消费者1 获得商品:商品-编号1
    消费者1 进入等待
    生产者2 生产商品:商品-编号2
    消费者2 获得商品:商品-编号2
    消费者2 进入等待
    生产者2 生产商品:商品-编号3
    消费者3 获得商品:商品-编号3
    消费者3 进入等待
    生产者1 生产商品:商品-编号4
    消费者1 获得商品:商品-编号4
    消费者1 进入等待
    生产者1 生产商品:商品-编号5
    消费者2 获得商品:商品-编号5
    消费者2 进入等待
    ...

    运行结果分析二(把notify改成notifyAll):

    每生产一件商品时调用notifyAll,都会把所有的消费者唤醒。

    消费者1 进入等待
    消费者3 进入等待
    消费者2 进入等待
    生产者2 生产商品:商品-编号1
    消费者3 进入等待
    消费者2 获得商品:商品-编号1
    消费者1 进入等待
    消费者2 进入等待
    生产者2 生产商品:商品-编号2
    消费者2 获得商品:商品-编号2
    消费者1 进入等待
    消费者3 进入等待
    消费者2 进入等待
    生产者2 生产商品:商品-编号3
    消费者2 获得商品:商品-编号3
    ...

    来源:http://www.taoweiji.cn/index.php/archives/112

  • 相关阅读:
    能量石
    Journey among Railway Stations —— 1J
    金明的预算方案
    css学习
    实验七
    计算圆的面积和窗体的跳转
    Android子菜单和选项菜单与上下文菜单的实现
    Android 对话框(Dialog)
    /etc/init.d 与 service 的 关系 。。。。。。。
    Linux && Aix 下 常用命令 dd
  • 原文地址:https://www.cnblogs.com/taoweiji/p/5188514.html
Copyright © 2011-2022 走看看