美文网首页
线程协作-生产者/消费者问题

线程协作-生产者/消费者问题

作者: Aluha_f289 | 来源:发表于2019-04-27 21:16 被阅读0次

    实例

    package demo3;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 线程与线程协作(通信),生产者/消费者
     * 生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。
     * (关键)该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
     * 要解决该问题:
     *      就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。
     *      同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者,通常采用线程间通信的方法解决该问题。
     *
     * 定义一个盘子类,可以放鸡蛋和取鸡蛋
     *      盘子里只能放一个鸡蛋,A线程专门往盘子里放鸡蛋,如果盘子里有鸡蛋,则一直等到盘子里没鸡蛋,
     *      B线程专门从盘子里取鸡蛋,如果盘子里没鸡蛋,则一直等到盘子里有鸡蛋。
     *
     */
    public class Plate {
    
    
            /** 装鸡蛋的盘子 */
            List<Object> eggs = new ArrayList<Object>();
    
        /**
         * 取鸡蛋
         */
        public synchronized Object getEgg() {
            //如果盘子为空、线程进入阻塞
            while (eggs.size() == 0) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Object egg = eggs.get(0);
            eggs.clear();// 清空盘子
            //盘子不为空(执行线程),唤醒阻塞队列的某线程到就绪队列
            notify();
            System.out.println("拿到鸡蛋");
            return egg;
        }
    
        /**
         *  放鸡蛋
         */
        public synchronized void putEgg(Object egg) {
            //判断盘子是否为空,放入一个鸡蛋,
            while (eggs.size() > 0) {
                try {
                    wait();//盘子非空,执行等待,这个A线程进入阻塞队列(在wait方法说明中,也推荐使用while)
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            eggs.add(egg);// 往盘子里放鸡蛋
            //假设CPU又调度了一个A线程
            notify();// 唤醒阻塞队列的某线程到就绪队列
            System.out.println("放入鸡蛋");
        }
    
        /**
         * 放鸡蛋线程
         */
        static class AddThread implements Runnable  {
            private Plate plate;
            private Object egg = new Object();
            public AddThread(Plate plate) {
                this.plate = plate;
            }
            public void run() {
                plate.putEgg(egg);
            }
    
        }
    
        /**
         * 取鸡蛋线程
         */
        static class GetThread implements Runnable  {
            private Plate plate;
            public GetThread(Plate plate) {
                this.plate = plate;
            }
            public void run() {
    
                plate.getEgg();
    
            }
    
        }
    
        public static void main(String args[]) {
            Plate plate = new Plate();
            for(int i = 0; i < 10; i++) {
                new Thread(new AddThread(plate)).start();
                new Thread(new GetThread(plate)).start();
            }
        }
    
    }
    
    

    运行结果

    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    放入鸡蛋
    拿到鸡蛋
    
    Process finished with exit code 0
    
    

    学习于https://blog.csdn.net/ghsau/article/details/7433673

    相关文章

      网友评论

          本文标题:线程协作-生产者/消费者问题

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