Java多线程阻塞队列下生产者消费者模式

51 阅读1分钟

本文已参与「新人创作礼」活动, 一起开启掘金创作之路。

高内聚低耦合的情况下线程操纵资源类

判断干活唤醒通知

严防多线程并发状态下的虚假唤醒

题目: 一个初始值为零的变量,两个线程对其交替操作,一个加1一个减1,来5轮

线程 操作(方法) 资源类 判断 干活 通知 防止虚假唤醒机制

image.png 多线程判断要用while防止虚假唤醒

image.png

传统版的生产者消费者模式代码(看注释)

package com.wsx.productConsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

        class shareDate {
            private int number = 0;
            private Lock lock = new ReentrantLock();
            private Condition condition = lock.newCondition();

            public void increment() {
                lock.lock();
                try {
                    //判断
                    while (number != 0) {
                        //不能生产
                        condition.await();
                    }
                    //生产
                    number++;
                    System.out.println(Thread.currentThread().getName() + "线程 \t" +number+ "生产");
                    //唤醒
                    condition.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }

            }

            public void decrement() {
                lock.lock();
                try {
                    //判断
                    while (number == 0) {
                        //不能消费
                        condition.await();
                    }
                    //消费
                    number--;
                    System.out.println(Thread.currentThread().getName() + "线程 \t" +number+ "消费");
                    //唤醒
                    condition.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }

            }

        }

        public class ProductConsumerDemo {
            public static void main(String[] args) {
                shareDate shareDate = new shareDate();
                new Thread(()->{
                    for (int i = 1; i <= 5 ; i++) {
                        shareDate.increment();
                    }
                },"AAA").start();

                new Thread(()->{
                    for (int i = 1; i <= 5 ; i++) {
                        shareDate.decrement();
                    }
                },"BBB").start();

                new Thread(()->{
                    for (int i = 1; i <= 5 ; i++) {
                        shareDate.increment();
                    }
                },"CCC").start();

                new Thread(()->{
                    for (int i = 1; i <= 5 ; i++) {
                        shareDate.decrement();
                    }
                },"DDD").start();
            }
        }

阻塞队列版的生产者消费者模式代码(看注释)

package com.wsx.productConsumer;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;


        class ProductConsumer {
            private volatile boolean FLAG = true;
            private AtomicInteger atomicInteger = new AtomicInteger();
            private BlockingQueue<String> blockingQueue = null;

            public ProductConsumer(BlockingQueue<String> blockingQueue) {
                this.blockingQueue = blockingQueue;
            }

            public void increment() throws Exception {
                String date = null;
                boolean retValue;
                while (FLAG) {
                    date = atomicInteger.incrementAndGet() + "";
                    retValue = blockingQueue.offer(date, 2L, TimeUnit.SECONDS);

                    if (retValue) {
                        System.out.println(Thread.currentThread().getName() + "\t" + date + "生产一个蛋糕");
                    } else {
                        System.out.println(Thread.currentThread().getName() + "\t" + date + "生产一个失败");
                    }
                    TimeUnit.SECONDS.sleep(1);
                }
                System.out.println(Thread.currentThread().getName()+"boss暂停不生产了");
            }

            public void decrement() throws Exception {
                String result = null;
                while (FLAG) {
                    result = blockingQueue.poll(2L, TimeUnit.SECONDS);
                    if(null == result || result.equalsIgnoreCase("")){
                        FLAG = false;
                        System.out.println(Thread.currentThread().getName()+"超过两秒没有取出蛋糕暂停");
                        return;
                    }
                    System.out.println(Thread.currentThread().getName()+"消费蛋糕成功");
                }
            }

            public void stop(){
                this.FLAG = false;
            }
        }

        public class ProductConsumerBlockingQueue {
            public static void main(String[] args){
                ProductConsumer productConsumer = new ProductConsumer(new ArrayBlockingQueue<>(10));

                new Thread(()->{
                    try {
                        System.out.println("生产线程启动");
                        for (int i = 1; i <= 5 ; i++) {
                            productConsumer.increment();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                },"prod").start();

                new Thread(()->{
                    try {
                        System.out.println("消费线程启动");
                        for (int i = 1; i <= 5 ; i++) {
                            productConsumer.decrement();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                },"consumer").start();

                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("boss叫停");
                productConsumer.stop();
            }
        }