java 实现生产者消费者模式的三种方法

很久以前使用基础同步的方式实现过一次。最近看到一篇文章使用多种方式进行实现,所以动手实践一下。

参考:https://zhuanlan.zhihu.com/p/20300609

 

关于生产者消费者问题、读者写者问题的最新研究,可以参考我的另一篇文章:

java 对生产者消费者问题、读者写者问题的简单研究

一、使用synchronized、wait、notifyAll

之前写过这种方案:

java 在同步代码中使用条件

具体代码为:

如果这样写,生产和消费(线程)不会同时进行。

生产者将一次性生产10个数据,然后消费者把所有数据都消费完,如此反复,没有起到“同时执行”/“相互执行”的效果。

一开始我觉得这种现象很诡异。后来才发现,“同时执行”涉及到另外一个“读者与写者”问题,生产者消费者模式并不要求生产和消费“同时执行”。

(2)使用Lock

既然可以使用普通的同步方法,那使用Lock也是可以的。

test.java

感觉这种写法比直接使用同步方法效果要好(问题:好在哪里?)。但是依然不能“同时执行”。

(3)使用BlockingQueue

test.java

重要的是put()方法和take()方法。

如果队列满了,put()会阻塞当前生产者线程,停止生产数据。如果队列的数据被消费(不为满),那么该生产者线程会被唤醒,继续生产,直到队列被填满。

如果队列为空,take()会阻塞当前消费者线程,停止消费数据。如果队列的数据有新数据(不为空),那么该消费者线程会被唤醒,继续消费,直到队列为空。

个人认为,Juc提供BlockingQueue的目的,就是为了解决“生产者消费者”问题。我们不需要再手写同步方法,不需要加锁,不需要维护自己的队列,BlockingQueue全都帮我们做了。使用这种方式是最方便的。

(当然BlockingQueue的底层依然是使用Lock实现的)

二、总结

以上三种实现方式,都有“读者和写者”问题(生产和消费不会同时进行)。

下次我将单独研究这个问题。

发表评论

电子邮件地址不会被公开。 必填项已用*标注