前言
先看一段代码,
class BlockingQueue { Queue<String> buffer = new LinkedList<>(); public synchronized void give(String s) { this.buffer.add(s); } public synchronized String take() { while (buffer.isEmpty()) { } return buffer.remove(); } }
上述代码看上去没有问题:take()
内部先判断队列是否为空,如果为空,就循环等待,直到另一个线程往队列中放入了一个任务,while()
循环退出,就可以返回队列的元素了。
但实际上while()
循环永远不会退出。因为线程在执行while()
循环时,已经在take()
入口获取了this
锁,其他线程根本无法调用give()
,因为give()
执行条件也是获取this
锁。
因此,执行上述代码,线程会在take()
中因为死循环而100%占用CPU资源。
如果深入思考一下,我们想要的执行效果是:
- 线程1可以调用
give()
不断往队列中添加任务;- 线程2可以调用
take()
从队列中获取任务。如果队列为空,则take()
应该等待,直到队列中至少有一个任务时再返回。
因此,多线程协调运行的原则就是:当条件不满足时,线程进入等待状态;当条件满足时,线程被唤醒,继续执行任务。
对于上述BlockingQueue
,我们先改造take()
方法,在条件不满足时,线程进入等待状态:
public synchronized String take() {
while (buffer.isEmpty()) {
this.wait