龙空技术网

面试官:用线程写一个生产者,消费者模式的代码?

Java识堂 3318

前言:

目前大家对“编写生产者消费者程序”都比较注意,姐妹们都需要学习一些“编写生产者消费者程序”的相关文章。那么小编在网上收集了一些对于“编写生产者消费者程序””的相关知识,希望同学们能喜欢,大家一起来了解一下吧!

介绍

有2种方法写,

1.是用Object类上的wait和notify方法来实现

2.用阻塞队列来实现(更优雅)

wait和notify

举一个多生产者,多消费者的例子,队列的大小为3,即队列大小为3时,生产者就不再生产

注意消费者和生产者都是用的notifyAll()[通知所有阻塞的线程]方法,而不是notify()[通知一个阻塞的线程]方法,因为有可能出现“生产者”唤醒“生产者”,消费者“唤醒”消费者的情况,因此有可能造成死锁,这里以1个消费者,3个生产者为例说一下,消费者1获得锁还没产品呢,阻塞,接着生产者1获得锁生产完了,然后生产者2获得锁后生产完了,再然后生产者3获得锁生产完了,最后生产者1获得锁了,然后阻塞了,现在好了生产者和消费者都阻塞了,造成了死锁。notifyAll()则不会造成死锁,接着上面的步骤,生产者3生产完了释放锁后,会通知所有阻塞的线程,因此消费者1肯定有机会拿到锁来进行消费

测试类

一部分结果

生产者0 生产生产者0 生产生产者0 生产消费者1 消费消费者1 消费消费者1 消费生产者1 生产
阻塞队列

为了方便大家理解阻塞队列,先介绍一下阻塞队列,再写代码,不然成效不高

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。

支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入的元素,直到队列不满

支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空

阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者从队列里取元素的线程。阻塞队列就是生产者用来存放元素,消费者用来获取元素的容器

插入和移除操作的4种处理方式

把上面实例用阻塞队列来改写,先自己写一个阻塞队列,实现BlockingQueue接口,这里只展示了一部分重写的方法

自己的阻塞队列

生产者

消费者

测试

这里将BlockingQueue的实现改为ArrayBlockingQueue,程序运行结果一样,和我们之前的例子比较,BlockingQueue其实就是不用我们自己写阻塞和唤醒的部分,直接看一下ArrayBlockingQueue的源码,其实和我自己实现的差不多,只不过是并发这部分源码用的是ReentLock,而我用的是synchronized

标签: #编写生产者消费者程序