Java中的LinkedBlockingDeque

时间:2020-01-09 10:35:12  来源:igfitidea点击:

Java中的LinkedBlockingDeque是BlockingDeque接口的实现,并且是java.util.concurrent包的一部分。就像LinkedBlockingQueue一样,LinkedBlockingDeque是一个可选绑定的阻塞队列,这意味着可以指定队列的容量,从而使其成为有界的,也可以不指定队列的容量,在这种情况下,双端队列的容量为Integer.MAX_VALUE。

Java中的LinkedBlockingDeque

LinkedBlockingDeque基于链接的节点,其中每个节点都保留对上一个和下一个节点的引用。除非每次插入都会使双端队列超出容量,否则将在每次插入时动态创建链接节点。

由于LinkedBlockingDeque是双端队列(deque)(双端队列),因此可以从队列的两端插入和删除元素,这就是LinkedBlockingDeque与ArrayBlockingQueue之类的BlockingQueue实现的不同之处,在该实现中,元素被添加到队列的末尾并从队列的头部检索。队列。

LinkedBlockingDeque实现是线程安全的。该类中的所有排队方法都在内部使用ReentrantLock自动实现其效果。

Java LinkedBlockingDeque构造函数

  • LinkedBlockingDeque()–未指定容量时,将创建容量为Integer.MAX_VALUE的LinkedBlockingDeque。
  • LinkedBlockingDeque(int Capacity)–创建具有给定(固定)容量的LinkedBlockingDeque。
  • LinkedBlockingDeque(Collection <?扩展E> c)–创建一个容量为Integer.MAX_VALUE的LinkedBlockingDeque,最初包含给定集合的元素,并以该集合的迭代器的遍历顺序添加。

LinkedBlockingDeque不允许空元素

BlockingDeque的实现不允许使用null元素。

public class LBDDemo {
  public static void main(String[] args) {
    BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>();
    try {
      blockingDeque.put(10);
      blockingDeque.put(null);
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

输出:

Exception in thread "main" java.lang.NullPointerException
	at java.base/java.util.concurrent.LinkedBlockingDeque.putLast(LinkedBlockingDeque.java:381)
	at java.base/java.util.concurrent.LinkedBlockingDeque.put(LinkedBlockingDeque.java:640)
	at com.theitroad.programs.LBDDemo.main(LBDDemo.java:12)

LinkedBlockingDeque Java示例

这是使用LinkedBlockingDeque的生产者-消费者示例。每个生产者线程在队列中放置5个整数值,作为消费者线程从队列中检索这些值。线程池只有两个线程,如果先执行consumer,则consumer会阻塞,因为使用了takeLast()方法。

public class LBDDemo {
  public static void main(String[] args) {
    BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>();
    ExecutorService executor = Executors.newFixedThreadPool(2);
    // 2 producer threads and one consumer thread
    executor.execute(new LinkedDQProducer(blockingDeque));
    executor.execute(new LinkedDQProducer(blockingDeque));
    executor.execute(new LinkedDQConsumer(blockingDeque));
    executor.shutdown();
  }
}    
// Producer
class LinkedDQProducer implements Runnable{
  BlockingDeque<Integer> blockingDeque;
  LinkedDQProducer(BlockingDeque<Integer> blockingDeque){
    this.blockingDeque = blockingDeque;
  }
  @Override
  public void run() {
    for(int i = 0; i < 5; i++){            
      blockingDeque.addFirst(i);
      System.out.println("Added to queue-" + i);            
    }
  }
}

//Consumer
class LinkedDQConsumer implements Runnable{
  BlockingDeque<Integer> blockingDeque;
  LinkedDQConsumer(BlockingDeque<Integer> blockingDeque){
    this.blockingDeque = blockingDeque;
  }
  @Override
  public void run() {
    for(int i = 0; i < 10; i++){
      try {
        System.out.println("Consumer retrieved- " + blockingDeque.takeLast());
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
}

输出:

Added to queue-0
Added to queue-0
Added to queue-1
Added to queue-1
Added to queue-2
Added to queue-3
Added to queue-4
Consumer retrieved- 0
Consumer retrieved- 0
Consumer retrieved- 1
Consumer retrieved- 1
Consumer retrieved- 2
Consumer retrieved- 3
Consumer retrieved- 4
Added to queue-2
Added to queue-3
Consumer retrieved- 2
Added to queue-4
Consumer retrieved- 3
Consumer retrieved- 4

Java LinkedBlockingDeque类方法

在像LinkedBlockingDeque这样的BlockingDeque实现中,用于添加和删除元素的方法有四种形式
一个抛出异常,第二个返回一个特殊值(取决于操作,为null或者false),第三个无限期阻塞当前线程,直到操作成功为止,第四个仅放弃给定的最大时间限制。

插入方式

  • addFirst(E e)–如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此双端队列的前面,如果当前没有可用空间,则抛出IllegalStateException。
  • addLast(E e)–如果可以立即在不影响容量限制的情况下在此双端队列的末尾插入指定的元素,如果当前没有可用空间,则抛出IllegalStateException。
  • offerFirst(E e)–如果可以在不违反容量限制的情况下立即执行此操作,则将指定的元素插入此双端队列的前面;如果成功,则返回true;如果当前没有可用空间,则返回false。
  • offerLast(E e)–如果可以立即这样做,而不会违反容量限制,则在此双端队列的末尾插入指定的元素;如果成功,则返回true;如果当前没有可用空间,则返回false。
  • putFirst(E e)–将指定的元素插入此双端队列的前面,如有必要,请等待空间变大。
  • putLast(E e)–将指定的元素插入此双端队列的末尾,如有必要,请等待空间变大。
  • offerFirst(E e,long timeout,TimeUnit unit)–将指定的元素插入此双端队列的前面,如果需要可用空间,则等待指定的等待时间。
  • offerLast(E e,long timeout,TimeUnit unit)–在此双端队列的末尾插入指定的元素,如果有必要腾出空间,则等待指定的等待时间。

清除方法

  • removeFirst()–检索并删除此双端队列的第一个元素。如果此双端队列为空,则引发异常。
  • removeLast()–检索并删除此双端队列的最后一个元素。如果此双端队列为空,则引发异常。
  • pollFirst()–检索并删除此双端队列的第一个元素,如果此双端队列为空,则返回null。
  • pollLast()–检索并删除此双端队列的最后一个元素;如果此双端队列为空,则返回null。
  • takeFirst()–检索并删除此双端队列的第一个元素,如有必要,请等待直到元素可用。
  • takeLast()–检索并删除此双端队列的最后一个元素,如有必要,请等待直到元素可用。
  • pollFirst(long timeout,TimeUnit unit)–检索并删除此双端队列的第一个元素,如果有必要使元素变为可用,则等待指定的等待时间。
  • pollLast(长超时,TimeUnit单位)–检索并删除此双端队列的最后一个元素,如果有必要使元素可用,则等待指定的等待时间。