Java中的ConcurrentLinkedDeque
时间:2020-01-09 10:35:12 来源:igfitidea点击:
Java中的ConcurrentLinkedDeque是线程安全的无限制并发双端队列。它将其元素存储为链接节点,其中每个节点都存储对上一个和下一个节点的引用。 Java中的ConcurrentLinkedDeque实现Deque接口,并且是java.util.concurrent包的一部分。
ConcurrentLinkedDeque与诸如LinkedBlockingDeque这样的阻塞式Deque实现的不同之处在于ConcurrentLinkedDeque是非阻塞的,因此该队列中的操作不会阻塞。由于ConcurrentLinkedDeque是非阻塞的,因此无法使用如putFirst(),takeFirst()或者putLast(),takeLast()之类的阻塞方法(如果需要的话)。
ConcurrentLinkedDeque与其对应的ConcurrentLinkedQueue相似,不同之处在于它是一个双端队列。这意味着ConcurrentLinkedDeque允许从两端插入和移除。 ConcurrentLinkedDeque具有诸如addFirst(),addLast(),removeFirst(),removeLast()之类的方法,以便于从两端插入和删除。
ConcurrentLinkedDeque不允许使用空元素
与大多数其他并发集合实现一样,此类不允许使用null元素。
public class ConcurrentLDQ { public static void main(String[] args) { Deque<Integer> conDeque = new ConcurrentLinkedDeque<>(); conDeque.add(10); conDeque.addLast(null); } }
输出:
Exception in thread "main" java.lang.NullPointerException at java.base/java.util.Objects.requireNonNull(Objects.java:221) at java.base/java.util.concurrent.ConcurrentLinkedDeque.linkLast(ConcurrentLinkedDeque.java:347) at java.base/java.util.concurrent.ConcurrentLinkedDeque.addLast(ConcurrentLinkedDeque.java:840) at com.theitroad.programs.ConcurrentLDQ.main(ConcurrentLDQ.java:11)
如我们所见,尝试将null添加到双端队列会导致NullPointerException。
Java ConcurrentLinkedDeque构造函数
- ConcurrentLinkedDeque()–构造一个空的双端队列。
- ConcurrentLinkedDeque(Collection <?extends E> c)–构造一个双端队列,此双端队列最初包含给定集合的元素,并以该集合的迭代器的遍历顺序添加。
ConcurrentLinkedDeque Java示例
这是使用ConcurrentLinkedDeque的Java生产者-消费者示例。有一个生产者线程和两个消费者线程。
public class ConcurrentLDQ { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(4); Deque<Integer> conDeque = new ConcurrentLinkedDeque<>(); // One Producer thread executor.execute(new ConProducer(conDeque)); // Two Consumer thread executor.execute(new ConConsumer(conDeque)); executor.execute(new ConConsumer(conDeque)); executor.shutdown(); } } //Producer class ConProducer implements Runnable{ Deque<Integer> conDeque; ConProducer(Deque<Integer> conDeque){ this.conDeque = conDeque; } @Override public void run() { for(int i = 0; i < 6; i++){ System.out.println("Adding to queue-" + i); conDeque.addFirst(i); } } } //Consumer class ConConsumer implements Runnable{ Deque<Integer> conDeque; ConConsumer(Deque<Integer> conDeque){ this.conDeque = conDeque; } @Override public void run() { for(int i = 0; i < 3; i++){ try { TimeUnit.MILLISECONDS.sleep(10); System.out.println("Thread Name -" + Thread.currentThread().getName() + " Consumer retrieved- " + conDeque.pollLast()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
输出:
Adding to queue-0 Adding to queue-1 Adding to queue-2 Adding to queue-3 Adding to queue-4 Adding to queue-5 Thread Name -pool-1-thread-3 Consumer retrieved- 0 Thread Name -pool-1-thread-2 Consumer retrieved- 1 Thread Name -pool-1-thread-3 Consumer retrieved- 2 Thread Name -pool-1-thread-2 Consumer retrieved- 3 Thread Name -pool-1-thread-3 Consumer retrieved- 4 Thread Name -pool-1-thread-2 Consumer retrieved- 5