image.png
阻塞队列:当线程队列是空时,从队列中获取元素的操作将会被阻塞;当线程队列是满时,往队列里添加元素的操作将会被阻塞。
Java 5 开始出现存在 java.util.concurrent 包下,阻塞队列是一个队列,当尝试从队列中出队并且队列为空时,或者尝试将项目入队并且队列已满时,它将阻塞。尝试从空队列中出队的线程被阻止,直到其他线程将一个项目插入队列中为止。尝试使一个项目进入完整队列的线程被阻塞,直到某个其他线程在队列中腾出空间为止,方法是使一个或多个项目出队或完全清除队列。
// 调用 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种不同的行为集意味着:
- 引发异常:如果无法立即进行尝试的操作,则会引发异常。
- 特殊值:如果无法立即尝试操作,则会返回一个特殊值(通常为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();
}
}