阻塞队列的实现原理

在这里贴一下有界阻塞队列的实现代码,总结一下自己的理解。底层用的是数组,其实就是一个循环队列。适合对并发时的数据处理。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BoundedBuffer {
//锁对象
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
//阻塞队列最大容量值为100
private final Object[] items = new Object[100];
private int putptr, takeptr, count;
//缓冲存放对象
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length){
//满了,进行等待
notFull.await();
}
items[putptr] = x;
if (++putptr == items.length){
//存放位置的指针要超过容量值了,则回到原点
putptr = 0;
}
++count;
//发信号,让空的走
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0){
//空了,进行等待。队列已经取完了。
notEmpty.await();
}
Object x = items[takeptr];
if (++takeptr == items.length){
//取出位置的指针要超过容量值了,则回到原点
takeptr = 0;
}
--count;
//发信号,让满的走
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}

测试


这里取两次,第一次就取完了,第二次就在等待放入数据。

结论

举一个简单的栗子说明,假设服务器或对外提供的接口并发的最高峰值访问是60,这时突然有80个访问请求需要处理。阻塞队列的应用场景就出现了。主要的作用与目的,就是起到缓冲的作用。存一个,取一个。在代码实现时,判断队列是否已经放满了和判断队列是否已经取空了时用了while,这是一个小小的细节。在等待 Condition 时,允许发生“虚假唤醒”,这通常作为对基础平台语义的让步。

谢谢你请我吃糖果

--------- 本文结束,感谢您的审阅 ---------
0%