(译)Java Concurrent系列--BlockingQueue
2017-08-30 14:19
281 查看
java.util.concurrent包中的
BlockingQueue接口是一个能够线程安全的插入和取出对象实例的阻塞队列。这篇文章将展示如何使用
BlockingQueue。
本文不会讨论如何利用
Java去实现一个
BlockingQueue。如果你有兴趣想去自己实现,你可以参考
Java Concurrency Tutorial里面关于
Blocking Queue部分的内容。
BlockingQueue Usage
BlockingQueue通常用于一个线程生产对象而另外一个线程消费这些对象的情景。下图是对这个原理的阐述:
![BlockingQueue原理][]http://tutorials.jenkov.com/images/java-concurrency-utils/blocking-queue.png]
生产线程会持续产生新对象并将其插入到阻塞队列之中,直到队列达到它存储容量的临界点。也就是说,阻塞队列的容量是有限的。如果阻塞队列到达了存储的临界点,当生产线程尝试插入新的对象时将会一直阻塞,直到消费线程从阻塞队列中取出一个对象。
消费线程则会持续的从阻塞队列取出对象并进行处理。当消费线程试着从一个空的队列取一个对象时,它会一直阻塞直到生产线程将一个对象放入队列中。
BlockingQueue Methods
BlockingQueue有4组不同的方法用于插入,删除和检查队列中的对象。如果请求的方法不能够立即执行时,每组方法的结果也是不同的。下表展示了这些方法的返回结果。
Throws Exception | Special Value | Blocks | Times Out | |
---|---|---|---|---|
Insert | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) |
Remove | remove(o) | poll() | take() | poll(timeout, timeunit) |
Examine | element() | peek() |
1. Throw Exception: 如果试图调用的操作无法立即执行,则抛出一个异常。
2. Special Value: 如果试图调用的操作无法立即执行,则返回一个特殊值(通常是true/false)。
3. Blocks: 如果试图调用的操作无法立即执行,该方法调用会一直阻塞直到可以立即执行为止。
4. Times Out: 如果试图调用的操作无法立即执行,该方法调用会一直阻塞直到可以立即执行为止,但是等待时间不会超过给定的时间间隔(
timeout)。返回一个特定值来表示该方法是否调用成功(通常是true/false)。
BlockingQueue中不能插入
null。如果你试图插入一个
null,
BlockingQueue将会抛出
NullPointerException异常。
BlcokingQueue内部所有元素都可以被访问,而不仅仅是头部和尾部的元素。例如,你将一个对象放入队列中等待处理,但你的应用想取消这个任务。这时,你就可以调用诸如
remove(o)方法来删除队列中的特定元素。但是这样的操作效率不会很高,因此,除非你迫不得已,否则尽量不要使用这类方法。
BlockingQueue Implementations
BlockingQueue是个接口,你需要使用它的实现类来使用它。
java.util.concurrent包中
BlockingQueue接口的实现类如下(原文中为Java 6,译者基于Java 8展示):
ArrayBlockingQueue
DelayQueue
LinkedBlcokingQueue
PriorityBlockingQueue
SynchronousQueue
Java BlockingQueue Example
下面展示了一个
BlockingQueue的例子。例子中使用了
BlockingQueue接口的实现类之一–
ArrayBlockingQueue。
首先,
BlockingQueueExample类在不同的线程中分别启动了一个生产者和一个消费者。生产者向共享的
BlockingQueue中插入字符串,消费者从共享的
BlockingQueue中取出字符串。
public class BlockingQueueExample { public static void main(String[] args) throws Exception { BlockingQueue queue = new ArrayBlockingQueue(1024); Producer producer = new Producer(queue); Consumer consumer = new Consumer(queue); new Thread(producer).start(); new Thread(consumer).start(); Thread.sleep(4000); } }
下面是生产者类。注意它在每次
put()调用时是如何休眠一秒钟的。这讲使得消费者在等待取出队列中对象时发生阻塞。
public class Producer implements Runnable{ protected BlockingQueue queue = null; public Producer(BlockingQueue queue) { this.queue = queue; } public void run() { try { queue.put("1"); Thread.sleep(1000); queue.put("2"); Thread.sleep(1000); queue.put("3"); } catch (InterruptedException e) { e.printStackTrace(); } } }
下面是消费者类。它只是从队列中取出对象,然后将它们打印到
System.out。
public class Consumer implements Runnable{ protected BlockingQueue queue = null; public Consumer(BlockingQueue queue) { this.queue = queue; } public void run() { try { System.out.println(queue.take()); System.out.println(queue.take()); System.out.println(queue.take()); } catch (InterruptedException e) { e.printStackTrace(); } } }
原文链接
相关文章推荐
- java concurrent系列2---BlockingQueue
- java.util.concurrent系列文章--(1)JDK1.5 并发集合
- java多线程学习-java.util.concurrent详解(四) BlockingQueue
- java.util.concurrent系列之--ConcurrentLinkedQueue
- java多线程学习-java.util.concurrent详解(四) BlockingQueue
- java.util.concurrent 之BlockingQueue
- Java 线程安全:BlockingQueue(阻塞算法) VS ConcurrentLinkedQueue(非阻塞算法)
- java.util.concurrent系列文章--(2)JDK1.5 锁机制
- 【Java】LinkedBlockingQueue、PriorityQueue and ConcurrentLinkedQueue
- Java多线程系列--“JUC集合”10之 ConcurrentLinkedQueue
- java多线程学习-java.util.concurrent详解(四) BlockingQueue
- Java多线程系列-Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
- java.util.concurrent系列之--LinkedBlockingDeque
- java.util.concurrent系列文章--(3)基于硬件同步原语的原子类型
- 《java.util.concurrent 包源码阅读》05 BlockingQueue
- java挑战高并发(14): LinkedBlockingQueue和ConcurrentLinkedQueue的区别及用法
- 《java.util.concurrent 包源码阅读》11 线程池系列之ThreadPoolExecutor 第一部分
- java.util.concurrent系列文章--(4)非阻塞算法简介
- 《java.util.concurrent 包源码阅读》15 线程池系列之ScheduledThreadPoolExecutor 第二部分