java多线程实现生产者、消费者模式

简述

生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向缓存区里生产数据,而消费者从缓存区里取出数据

什么是生产者?

  生产者指的是负责生产数据的模块。

什么是消费者?

  消费者指的是负责消费数据的模块。

什么是缓冲区?

   消费者不能直接使用生产者的数据,它们之间有个缓冲区。生产者将生产好的数据放入缓冲区,消费者从缓冲区取要处理的数据。

注:上面的的模块指的可能是:方法、对象、线程等。

java多线程实现生产者、消费者模式_第1张图片

缓冲区是实现并发协助的核心,设置缓冲区有几个好处:

1.实现线程的并发协作

  有了缓冲区以后,生产者线程只需往缓冲区里面放置数据,不需要管消费者消费的情况。同样,消费者只需要从缓冲区取数据处理,不需要管生产者生产的情况。 这样就从逻辑上实现了生  产者线程和消费者线程的分离。

2.解耦了生产者和消费者

  生产者不需要和消费者直接打交道。

3.解决忙闲不均,提高效率

  生产者生产数据慢时,缓冲区仍有数据,不影响消费者消费。消费者处理数据慢时,生产者仍然可以继续往缓冲区里面放置数据 。

代码实现

1 .使用 lock锁机制实现, 通过创建Lock对象,采用lock()加锁,unlock()解锁。


class Resource {
    private int num;
    private Lock reentrantLock = new ReentrantLock();
    private Condition condition =  reentrantLock.newCondition();

    //生产
    public void add(){
        //消费了再生产 不等于0时循坏等待
        reentrantLock.lock();
        try {
            while (num!=0){
                condition.await();
            }
            System.out.println(Thread.currentThread().getName()+"生产 +1");
            num++;
            condition.signalAll();//通知消费 唤醒所有wait状态的线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }

    public void minus(){
        //生产了再消费 等于0时循坏等待
        reentrantLock.lock();
        try {
            while (num==0){
                condition.await();
            }
            System.out.println(Thread.currentThread().getName()+"消费 -1");
            num--;
            condition.signalAll();//通知消费 唤醒所有wait状态的线程
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }
    }
}
public class ProductionAndConsumer {

    public static void main(String[] args) {
        Resource resource = new Resource();
        for (int i = 1; i <6 ; i++) {
            new Thread(()->{
                resource.add();
            },"生产线程").start();
        }
        for (int i = 1; i <6 ; i++) {
            new Thread(()->{
                resource.minus();
            },"消费线程").start();
        }
    }

}

运行输出:

java多线程实现生产者、消费者模式_第2张图片

2.使用阻塞队列实现


public class ProductionAnDConsumerBlockingQueue {

    public static void main(String[] args) throws InterruptedException {
        Resource resource = new Resource(new LinkedBlockingQueue(10));
        new Thread(()->{
            try {
                resource.prod();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"prod").start();
        new Thread(()->{
            try {
                resource.consumer();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"consumer").start();



        TimeUnit.SECONDS.sleep(5);

        System.out.println("按下关闭开关,停止生产、消费");
        resource.stop();
    }
    static class Resource {
        ///生产开关
        private volatile boolean flag = true;
        private AtomicInteger num = new AtomicInteger();
        //阻塞队列
        private BlockingQueue queue = null;

        public Resource(BlockingQueue queue) {
            this.queue = queue;
        }
        /*
         *生产队列
         **/
        public void prod() throws InterruptedException {
            String temp  ;
            boolean offer;
            while (flag){
                temp =   num.incrementAndGet()+"";
                //生产模式开启
                offer = queue.offer(temp, 2l, TimeUnit.SECONDS);
               // if(offer){
                    System.out.println(Thread.currentThread().getName()+"生产成功,插入队列成功:"+temp);
//                }else {
//                    System.out.println("生产失败,插入队列失败:"+temp);
//                }
                //模拟业务操作耗时时间
                TimeUnit.SECONDS.sleep(1);
            }

            System.out.println("生产总开关关闭了 状态:"+flag);
        }


        /*
         * 消费队列
         **/
        public void consumer() throws InterruptedException{
            String poll;
            while (flag){
                poll = (String) queue.poll(2l, TimeUnit.SECONDS);
                if(poll==null||poll.equalsIgnoreCase("")){
                    System.out.println("等待超时,停止消费");
                    this.flag=false;
                    return;
                }
                System.out.println(Thread.currentThread().getName()+"消费成功"+poll);
            }
            System.out.println("消费队列检查到总开关关闭了 状态:"+flag);
        }


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

运行输出

java多线程实现生产者、消费者模式_第3张图片

你可能感兴趣的:(多线程,Java,java,多线程,并发编程)