本文内容如有错误、不足之处,欢迎技术爱好者们一同探讨,在本文下面讨论区留言,感谢。
简述
阻塞队列:当线程队列是空时,从队列中获取元素的操作将会被阻塞;当线程队列是满时,往队列里添加元素的操作将会被阻塞。
Java 5 开始出现存在 java.util.concurrent 包下,阻塞队列是一个队列,当尝试从队列中出队并且队列为空时,或者尝试将项目入队并且队列已满时,它将阻塞。尝试从空队列中出队的线程被阻止,直到其他线程将一个项目插入队列中为止。尝试使一个项目进入完整队列的线程被阻塞,直到某个其他线程在队列中腾出空间为止,方法是使一个或多个项目出队或完全清除队列。
原理
原理示意图片:
图片地址:http://tutorials.jenkov.com/java-concurrency/blocking-queues.html
下面是一个简单的BlockQueue的实现:
public class BlockingQueue {
private List queue = new LinkedList();
private int limit = 10;
public BlockingQueue(int limit){
this.limit = limit;
}
public synchronized void enqueue(Object item)throws InterruptedException {
while(this.queue.size() == this.limit) {
wait();
}
if(this.queue.size() == 0) {
notifyAll();
}
this.queue.add(item);
}
public synchronized Object dequeue() throws InterruptedException{
while(this.queue.size() == 0){
wait();
}
if(this.queue.size() == this.limit){
notifyAll();
}
return this.queue.remove(0);
}
}
操作代码:
// 调用 BlockingQueue 方法的Java程序演示
import java.util.concurrent.*;
import java.util.*;
public class GFG {
public static void main(String[] args)
throws InterruptedException
{
// ArrayBlockingQueue 的边界大小
int capacity = 5;
// 创建 ArrayBlockingQueue
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(capacity);
// 使用put()方法添加元素
queue.put("StarWars");
queue.put("SuperMan");
queue.put("Flash");
queue.put("BatMan");
queue.put("Avengers");
// 打印队列
System.out.println("queue contains "+ queue);
// 移除一些元素
queue.remove();
queue.remove();
queue.put("CaptainAmerica");
queue.put("Thor");
System.out.println("queue contains " + queue);
}
}
输出结果:
queue contains [StarWars, SuperMan, Flash, BatMan, Avengers]
queue contains [Flash, BatMan, Avengers, CaptainAmerica, Thor]
操作
BlockingQueue方法有四种形式,它们以不同的方式处理操作,这些操作可能无法满足开发需求,但将来可能会满足:第一种抛出异常,第二种返回特殊值( null或false,具体取决于操作),第三个块将无限期地阻塞当前线程,直到操作成功为止;第四个块仅在给定的最大时间限制内超时。
下表总结了这些方法:
方法类型 | 抛出异常 | 特殊值 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time,unit) |
检查 | element() | peek() | 无 | 无 |
这4种不同的行为集意味着:
扫描二维码关注公众号,回复:
8623734 查看本文章
- 引发异常:如果无法立即进行尝试的操作,则会引发异常。
- 特殊值:如果无法立即尝试操作,则会返回一个特殊值(通常为true / false)。
- 阻塞:如果无法立即进行尝试的操作,则该方法调用将一直阻塞直到可行为止。
- 超时:如果无法立即进行尝试的操作,则该方法调用将一直阻塞直到成功,但等待时间不得长于给定的超时。返回一个特殊值,告诉操作是否成功(通常为true / false)。
下面是一个生产者消费者的案例使用BlockQueue:
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
参考资料
Blocking Queues
Interface BlockingQueue
Java BlockingQueue
BlockingQueue Interface in Java