前言
前面我总结了一下关于BlockingQueue和BlockingQueue实现类的相关知识点,现在接下来看concurrent包的另一个接口BlockingDeque,BlockingDeque 接口表示一个线程安放入和提取实例的双端队列。就是说两段都可以进出的,实际上和单端的也差不多,就是单端变双端。
抛异常 | 特定值 | 阻塞 | 超时 |
---|---|---|---|
插入 | addFirst(o) | offerFirst(o) | putFirst(o) |
移除 | removeFirst(o) | pollFirst(o) | takeFirst(o) |
检查 | getFirst(o) | peekFirst(o) |
实现类
- LinkedBlockingDeque
接口源码
/*
我把注释全删了
*/
package java.util.concurrent;
import java.util.*;
// Deque继承了Queue
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
void addFirst(E e);
void addLast(E e);
boolean offerFirst(E e);
boolean offerLast(E e);
void putFirst(E e) throws InterruptedException;
void putLast(E e) throws InterruptedException;
boolean offerFirst(E e, long timeout, TimeUnit unit)
throws InterruptedException;
boolean offerLast(E e, long timeout, TimeUnit unit)
throws InterruptedException;
E takeFirst() throws InterruptedException;
E takeLast() throws InterruptedException;
E pollFirst(long timeout, TimeUnit unit)
throws InterruptedException;
E pollLast(long timeout, TimeUnit unit)
throws InterruptedException;
boolean removeFirstOccurrence(Object o);
boolean removeLastOccurrence(Object o);
// *** BlockingQueue methods ***
// 所以以下是BlockingQueue相关的方法
boolean add(E e);
boolean offer(E e);
void put(E e) throws InterruptedException;
boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException;
E remove();
E poll();
E take() throws InterruptedException;
E poll(long timeout, TimeUnit unit)
throws InterruptedException;
E element();
E peek();
boolean remove(Object o);
public boolean contains(Object o);
public int size();
Iterator<E> iterator();
// *** Stack methods ***
void push(E e);
}
LinkedBlockingQueue
这个实现类只有一个,我就不另外开一章来讲了,就看看这个就好了。
怎么用?
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
public class Main22 {
public static void main(String[] args) {
BlockingDeque<Integer> bd = new LinkedBlockingDeque<>();
Pro pro = new Pro(bd);
Con1 con = new Con1(bd);
pro.start();
con.start();
}
}
class Pro extends Thread {
private BlockingDeque<Integer> bd;
public Pro(BlockingDeque<Integer> bd) {
this.bd = bd;
}
@Override
public void run() {
try {
bd.putFirst(1);
// 不加这个延迟,几乎是一个顺序操作
Thread.sleep(2);
bd.putFirst(2);
bd.putFirst(3);
System.out.println(bd.toString());
System.out.println(Thread.currentThread().getName() + " " + bd.takeFirst());
System.out.println(bd.toString());
System.out.println(Thread.currentThread().getName() + " " + bd.takeLast());
System.out.println(bd.toString());
System.out.println(Thread.currentThread().getName() + " " + bd.take());
bd.putFirst(4);
bd.putFirst(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Con1 extends Thread {
private BlockingDeque<Integer> bd;
public Con1(BlockingDeque<Integer> bd) {
this.bd = bd;
}
@Override
public void run() {
try {
bd.putLast(11);
Thread.sleep(2);
bd.putLast(22);
bd.putLast(33);
System.out.println(bd.toString());
System.out.println(Thread.currentThread().getName() + " " + bd.takeFirst());
System.out.println(bd.toString());
System.out.println(Thread.currentThread().getName() + " " + bd.takeLast());
System.out.println(bd.toString());
System.out.println(Thread.currentThread().getName() + " " + bd.take());
bd.putLast(44);
bd.putLast(55);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果
[3, 2, 1, 11]
Thread-0 3
[2, 1, 11]
Thread-0 11
[2, 1]
Thread-0 2
[5, 4, 1, 22, 33]
Thread-1 5
[4, 1, 22, 33]
Thread-1 33
[4, 1, 22]
Thread-1 4
看看源码
public void putFirst(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// 需要包装一个Node
Node<E> node = new Node<E>(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
while (!linkFirst(node))
notFull.await();
} finally {
lock.unlock();
}
}
private boolean linkFirst(Node<E> node) {
// assert lock.isHeldByCurrentThread();
// 如果比容量大返回false
if (count >= capacity)
return false;
// 否则就把节点挂在最前面
Node<E> f = first;
node.next = f;
first = node;
if (last == null)
last = node;
else
f.prev = node;
++count;
notEmpty.signal();
return true;
}
// 没有指定容量就指定容量为Max Integer
public LinkedBlockingDeque() {
this(Integer.MAX_VALUE);
}
// 如果指定了容量,就以指定容量为capacity
public LinkedBlockingDeque(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
}
// 与put相似,不过是相反过程
public E takeLast() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E x;
while ( (x = unlinkLast()) == null)
notEmpty.await();
return x;
} finally {
lock.unlock();
}
}
private E unlinkLast() {
// assert lock.isHeldByCurrentThread();
Node<E> l = last;
if (l == null)
return null;
Node<E> p = l.prev;
E item = l.item;
l.item = null;
l.prev = l; // help GC
last = p;
if (p == null)
first = null;
else
p.next = null;
--count;
notFull.signal();
return item;
}
后记
其实这个BlockingDeque并不算很难,这只是满足了一种需求而创造出来的,实质上还是属于BlockingQueue范畴的东西。