ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
![](https://cdn.zimug.com/wx-zimug.png) 在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue,本文为系列文章第七篇。 `BlockingDeque`接口和[`BlockingQueue`](http://www.zimug.com/java/concurrency/java%e5%b9%b6%e5%8f%91%e7%bc%96%e7%a8%8b%e5%b7%a5%e5%85%b7%e7%b1%bbjuc%e4%b9%8b%e4%b8%80%ef%bc%9ablockingqueue%e9%98%bb%e5%a1%9e%e9%98%9f%e5%88%97/.html) 接口一样都是在`java.util.concurrent`中定义的,它代表了一个线程安全的“双端队列”,以线程安全的方式向队列中添加元素或获取元素。本篇文章将带大家进一步了解`BlockingDeque`。 > `deque`是 "Double Ended Queue "的缩写。因此“双端队列”的含义就是可以从两端(队首或队尾)插入和取出元素的队列。 如果某个线程既生产又消费同一个队列的元素,那么就可以使用`BlockingDeque`双端队列。如果生产线程需要在队列的两端插入,而消费线程需要从队列的两端删除,也可以只使用`BlockingDeque`双端队列。参考下面的图进行理解 ![](http://cdn.zimug.com/6788ae32d22b8b7d399ca9a7b5f4502a) 一个线程生产元素并将它们插入到队列两端中的任何一端。如果`BlockingDeque`当前是满的,插入线程将被阻塞,直到移除线程从`BlockingDeque`中取出一个元素。如果`BlockingDeque`当前为空,那么移除线程将被阻塞,直到插入线程将一个元素插入到`BlockingDeque`中。 ## BlockingDeque 方法 `BlockingDeque`有4组不同的方法,用于插入、删除和检查deque中的元素。每组方法在所要求的操作不能被立即执行的情况下表现也有所不同。参考下面的表格 |队首操作|抛出异常|返回特定值|阻塞后一直等待|阻塞后等待超时| |---|---|---|---|---| |插入对象|addFirst(o)|offerFirst(o)|putFirst(o)|offerFirst(o, timeout, timeunit)| |移除对象|removeFirst(o)|pollFirst()|takeFirst()|pollFirst(timeout, timeunit)| |检查对象存在|getFirst()|peekFirst()||| |队尾操作|抛出异常|返回特定值|阻塞后一直等待|阻塞后等待超时| |---|---|---|---|---| |插入对象|addLast(o)|offerLast(o)|putLast(o)|offerLast(o, timeout, timeunit)| |移除对象|removeLast(o)|pollLast()|takeLast()|pollLast(timeout, timeunit)| |检查对象存在|getLast()|peekLast()||| 大家可以看到,这些方法和和[`BlockingQueue`](http://www.zimug.com/java/concurrency/java%e5%b9%b6%e5%8f%91%e7%bc%96%e7%a8%8b%e5%b7%a5%e5%85%b7%e7%b1%bbjuc%e4%b9%8b%e4%b8%80%ef%bc%9ablockingqueue%e9%98%bb%e5%a1%9e%e9%98%9f%e5%88%97/.html) 的方法有些相似,只是在方法的基础上加了xxxFirst和xxxLast,所以可以参考我之前的文章对比学习),上面的方法的四种行为分别的含义是 1. **抛出异常**: 如果调用方法后不能立即响应结果(空队列或满队列),则抛出异常。 2. **返回特定值**: 如果调用方法后不能立即响应结果(空队列或满队列),则返回特定的值(通常是true/false),true表示方法执行成功,否则表示方法执行失败。 3. **阻塞后一直等待**: 如果调用方法后不能立即响应结果(空队列或满队列),该方法将被阻塞一直处于等待状态。 4. **阻塞后等待超时**: 如果调用方法后不能立即响应结果(空队列或满队列),该方法将在一定时间范围内被阻塞等待,也就是在超时时间范围内阻塞。当超出超时时间之后,方法线程将不再阻塞,而是返回一个特定的值(通常是true/false),true表示方法执行成功,否则表示方法执行失败。 ## BlockingDeque继承BlockingQueue BlockingDeque接口继承了BlockingQueue接口。这意味着你可以将BlockingDeque作为一个BlockingQueue使用。如果你这样做,各种插入方法将把元素添加到deque的末尾,而移除方法将从deque的队首移除元素。BlockingQueue接口的插入和删除方法,就是这样做的。 下面是BlockingQueue的方法在BlockingDeque实现中的作用对照表 |BlockingQueue|BlockingDeque| |-----|-----| |add()|addLast()| |offer()|offerLast()| |put()|putLast()| ||| |remove()|removeFirst()| |poll|pollFirst()| |take()|takeFirst()| ||| |element()|getFirst()| |peek()|peekFirst()| ## BlockingDeque 接口实现类 `BlockingDeque`是一个接口,所以当我们真正对它进行实例化的时候,需要使用它的接口实现类。在`java.util.concurrent`包中的`LinkedBlockingDeque`方法实现了`BlockingDeque`接口。 其使用方法也与[`BlockingQueue`](http://www.zimug.com/java/concurrency/java%e5%b9%b6%e5%8f%91%e7%bc%96%e7%a8%8b%e5%b7%a5%e5%85%b7%e7%b1%bbjuc%e4%b9%8b%e4%b8%80%ef%bc%9ablockingqueue%e9%98%bb%e5%a1%9e%e9%98%9f%e5%88%97/.html) 大同小异,所以此处只做简单的介绍。 ~~~ //初始化一个LinkedBlockingDeque BlockingDeque<String> deque = new LinkedBlockingDeque<String>(); deque.addFirst("1");//向队首添加元素 deque.addLast("2"); //向队尾添加元素 String two = deque.takeLast(); //从队尾获取元素 String one = deque.takeFirst(); //从队首获取元素 ~~~