一文带你掌握Java LinkedBlockingQueue
Java LinkedBlockingQueue 是一种线程安全的阻塞队列,实现了 BlockingQueue 接口,并通过链表的形式保存元素。本文将详细介绍 LinkedBlockingQueue 的使用方法和注意事项。
LinkedBlockingQueue 的初始化
LinkedBlockingQueue 的构造函数提供了多种初始化方式:
LinkedBlockingQueue()
: 创建一个容量为 Integer.MAX_VALUE 的 LinkedBlockingQueue。LinkedBlockingQueue(int capacity)
: 创建指定容量的 LinkedBlockingQueue。LinkedBlockingQueue(Collection<? extends E> c)
: 创建包含指定元素集合的 LinkedBlockingQueue。
LinkedBlockingQueue 的入队和出队
LinkedBlockingQueue 提供了两种入队操作:put()
和 offer()
。当队列已满时,put()
方法会阻塞当前线程,而 offer()
方法会返回 false。
示例 1:使用 offer()
方法向队列中添加元素:
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
System.out.println(queue.offer("element1")); // 输出 true
System.out.println(queue.offer("element2")); // 输出 true
System.out.println(queue.offer("element3")); // 输出 false
示例 2:使用 put()
方法向队列中添加元素:
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
queue.put("element1"); // 阻塞当前线程直到插入成功
queue.put("element2"); // 阻塞当前线程直到插入成功
queue.put("element3"); // 阻塞当前线程直到插入成功
LinkedBlockingQueue 提供了两种出队操作:take()
和 poll()
。当队列为空时,take()
方法会阻塞当前线程,而 poll()
方法会返回 null。
示例 3:使用 poll()
方法从队列中获取元素:
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
System.out.println(queue.offer("element1")); // 输出 true
System.out.println(queue.offer("element2")); // 输出 true
System.out.println(queue.poll()); // 输出 element1
System.out.println(queue.poll()); // 输出 element2
System.out.println(queue.poll()); // 输出 null
示例 4:使用 take()
方法从队列中获取元素:
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(2);
new Thread(() -> {
try {
System.out.println(queue.take()); // 阻塞当前线程直到获取到元素
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(1000);
queue.put("element1");
本例中,开启了一个新线程,使用 take()
方法获取队列中的元素,主线程等待 1 秒后向队列中添加元素。由于 take()
方法会阻塞当前线程直到获取到元素,因此在元素添加到队列后,新线程会立即获取该元素并输出。
LinkedBlockingQueue 的 blocking 和 unblocking 两种操作
LinkedBlockingQueue 提供了两种阻塞和非阻塞的操作方法。
- 批量操作:
drainTo(Collection<? super E> c)
: 将队列中的所有元素转移到指定集合中。drainTo(Collection<? super E> c, int maxElements)
: 将队列中的最多 maxElements 个元素转移到指定集合中。
示例 5:使用 drainTo()
方法将队列中的元素转移到另一个集合中:
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.offer("element1");
queue.offer("element2");
List<String> list = new ArrayList<>();
// 将队列中的所有元素转移到 list 中
queue.drainTo(list);
System.out.println(list); // 输出 [element1, element2]
- 检索操作:
- 【阻塞】
take()
:若队列为空,则等待(阻塞当前线程);否则,获取并返回队列头。 poll()
: 若队列为空,则返回 null;否则,获取并返回队列头。peek()
: 若队列为空,则返回 null;否则,获取但不移除队列头。
- 【阻塞】
示例 6:从队列中获取元素的方法:
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.offer("element1");
System.out.println(queue.take()); // 输出 element1
System.out.println(queue.poll()); // 输出 null
System.out.println(queue.peek()); // 输出 null
本例中,向空队列中添加了一个元素后,使用 take()
方法获取队列头部的元素,由于队列不为空,该方法会立即返回并输出该元素。接着使用 poll()
和 peek()
方法分别对队列进行检索,但由于队列已经为空了,因此它们会返回 null。
总而言之,LinkedBlockingQueue 在实现线程安全的阻塞队列的同时,也提供了大量实用的操作方法,可以极大地方便开发者的编程工作。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文带你掌握Java LinkedBlockingQueue - Python技术站