美文网首页
java多线程-生产者消费者模式

java多线程-生产者消费者模式

作者: YiiY34 | 来源:发表于2022-04-20 14:50 被阅读0次
    Thread、Runnable、Callable&&Future
    new Thread() {
                @Override
                public void run() {
                    System.out.println("Thread实现");
                }
            }.start();
    
     new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Runnable实现");
                }
            }).start();
    
     Callable<String> callable = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println("Callable实现");
                    return "Callable的返回值";
                }
            };
     FutureTask<String> futureTask = new FutureTask<>(callable);
     new Thread(futureTask).start();
     String result = futureTask.get();//Callable的返回值
    

    其中futureTask.get()会获取callable的返回值,需要在start()方法后执行并会阻塞当前线程等待callable执行完毕

    生产者消费者模式

    生产消费者模式是一个十分经典的多线程协作的模式,可以实现对任务数量的控制,防止任务过多,导致程序处理不来。

    简单实现等待唤醒机制

    用顾客和厨师来描述消费者和生产者

    厨师做好了菜,通知顾客食用,顾客吃完了叫厨师接着做!!

    //生产者-厨师
    class Cooker extends Thread {
        @Override
        public void run() {
            /**
             * 1.判断是否有食物
             * 2.如果有就等待 || 如果没有就制作
             * 3.制作完成通知顾客享用
             */
            while (true) {
                synchronized (Desk.lock) {
                    if (Desk.count == 0) {
                        break;
                    } else {
                        if (Desk.flag) {
                            try {
                                Desk.lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        } else {
                            System.out.println("厨师正在制作食物");
                            Desk.flag = true;
                            Desk.lock.notifyAll();
                        }
                    }
                }
            }
        }
    }
    
    //消费者-顾客
    class Foodie extends Thread {
        @Override
        public void run() {
            /**
             * 1.判断是否有食物
             * 2.如果没有就等待 || 如果有就吃掉
             * 3.吃完之后通知厨师
             */
            while (true) {
                synchronized (Desk.lock) {
                    if (Desk.count == 0) {
                        break;
                    } else {
                        if (Desk.flag) {//判断是否有食物
                            //开始享用
                            System.out.println("顾客开始享用食物,当前库存" + (Desk.count-1));
                            Desk.flag = false;
                            Desk.count--;
                            Desk.lock.notifyAll();
                        } else {
                            //等待制作
                            try {
                                //使用什么对象作锁就必须用那个对象调用wait()和notify()
                                Desk.lock.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
    
                    }
                }
            }
        }
    }
    
    class Desk {
        /**
         * 定义一个标记判断桌子上是否有食物
         * true-桌上有 顾客可以享用
         * false-桌上没有 顾客需要等待
         */
        public static boolean flag = false;
    
        //每天限量5个
        public static int count = 5;
    
        //锁对象
        public final static Object lock = new Object();
    }
            /**
             * 生产者&&消费者
             * 生产者==》厨师
             * 消费者==》顾客
             */
            Foodie foodie=new Foodie();
            Cooker cooker=new Cooker();
            foodie.start();
            cooker.start();
    
    厨师正在制作食物
    顾客开始享用食物,当前库存4
    厨师正在制作食物
    顾客开始享用食物,当前库存3
    厨师正在制作食物
    顾客开始享用食物,当前库存2
    厨师正在制作食物
    顾客开始享用食物,当前库存1
    厨师正在制作食物
    顾客开始享用食物,当前库存0
    

    其中notifyAll()wait()方法,使用什么对象作锁就必须用那个对象调用

    阻塞队列实现等待唤醒机制

    常见BlockingQueue
    ArrayBlockingQueue:底层是数组,有界
    LinkedBlockingQueue:底层是链表,无界。PS:不是真正的无界,最大为int的最大值

    public class Demo {
        public static void main(String[] args) {
            //创建一个阻塞队列
            ArrayBlockingQueue<String> list = new ArrayBlockingQueue(1);
    
            //创建线程并开启
            Cooker cooker = new Cooker(list);
            Foodie foodie = new Foodie(list);
            cooker.start();
            foodie.start();
        }
    }
    
    class Cooker extends Thread {
    
    
        private ArrayBlockingQueue<String> list;
        private int count = 10;
    
        public Cooker(ArrayBlockingQueue<String> list) {
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true) {
                if (count == 0)
                    break;
                try {
                    String food = System.currentTimeMillis() + "制作的食物";
                    Thread.sleep(1000);
                    System.out.println(food);
                    list.put(food);
                    count--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    class Foodie extends Thread {
    
        private ArrayBlockingQueue<String> list;
    
        public Foodie(ArrayBlockingQueue<String> list) {
            this.list = list;
        }
    
        @Override
        public void run() {
            while (true)
                try {
                    Thread.sleep(2000);
                    System.out.println("享用" + list.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    }
    

    相关文章

      网友评论

          本文标题:java多线程-生产者消费者模式

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