日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java阻塞队列 LinkedBlockingDeque

發布時間:2024/9/30 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java阻塞队列 LinkedBlockingDeque 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/120833494
本文出自【趙彥軍的博客】

Java隊列 Queue
Java隊列 Deque
Java隊列 PriorityQueue
Java棧 Stack
Java阻塞隊列 LinkedBlockingDeque

文章目錄

  • LinkedBlockingDeque
  • 源碼
    • 增加操作
    • 刪除操作
    • 訪問操作
  • BlockingQueue
  • 核心要點
  • 實戰

LinkedBlockingDeque

LinkedBlockingDeque類實現了BlockingDeque接口。閱讀BlockingDeque文本以獲取有關的更多信息。

Deque來自“雙端隊列” 這個詞。Deque是一個隊列,你可以在插入和刪除隊列兩端的元素。

LinkedBlockingDeque是一個Deque,如果一個線程試圖從中獲取一個元素,而隊列空的,不管線程從哪一端試圖獲取元素,都會被阻塞。

以下是實例化和使用LinkedBlockingDeque的例子:

BlockingDeque<String> deque = new LinkedBlockingDeque<String>();deque.addFirst("1"); deque.addLast("2");String two = deque.takeLast(); String one = deque.takeFirst();

LinkedBlockingDeque的底層數據結構是一個雙端隊列,該隊列使用鏈表實現,其結構圖如下:

源碼

LinkedBlockingDeque與LinkedBlockingQueue的實現大體上類似,區別在于LinkedBlockingDeque提供的操作更多。并且LinkedBlockingQueue內置兩個鎖分別用于put和take操作,而LinkedBlockingDeque只使用一個鎖控制所有操作。因為隊列能夠同時在頭尾進行put和take操作,所以使用兩個鎖也需要將兩個鎖同時加鎖才能保證操作的同步性,不如只使用一個鎖的性能好。

同步節點相比LinkedBlockingQueue多了一個prev字段。

static final class Node<E> {E item;Node<E> prev;Node<E> next;Node(E x) {item = x;} }

增加操作

增加操作相比LinkedBlockingQueue只能在隊列尾部增加,它能在隊列的頭尾兩端都進行增加操作。

public void addFirst(E e) {// 復用offer方法if (!offerFirst(e))throw new IllegalStateException("Deque full"); }public void addLast(E e) {if (!offerLast(e))throw new IllegalStateException("Deque full"); }public boolean offerFirst(E e) {if (e == null) throw new NullPointerException();// 構造節點Node<E> node = new Node<E>(e);final ReentrantLock lock = this.lock;lock.lock();try {// 插入到隊列頭部return linkFirst(node);} finally {lock.unlock();} }private boolean linkFirst(Node<E> node) {// assert lock.isHeldByCurrentThread();// 如果隊列已滿,返回falseif (count >= capacity)return false;// 獲取頭節點,將自己的 next字段指向頭節點,然后設置自己為頭節點Node<E> f = first;node.next = f;first = node;// 如果隊列為空,尾節點也指向自己if (last == null)last = node;elsef.prev = node;++count;// 喚醒等待獲取元素的線程notEmpty.signal();return true; }public boolean offerLast(E e) {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);final ReentrantLock lock = this.lock;lock.lock();try {// 插入到隊列尾部return linkLast(node);} finally {lock.unlock();} }private boolean linkLast(Node<E> node) {// assert lock.isHeldByCurrentThread();// 如果隊列已滿,返回falseif (count >= capacity)return false;// 將自己設置為尾節點Node<E> l = last;node.prev = l;last = node;// 如果隊列為空,頭節點也指向自己if (first == null)first = node;elsel.next = node;++count;// 喚醒等待獲取元素的線程notEmpty.signal();return true; }public void putFirst(E e) throws InterruptedException {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);final ReentrantLock lock = this.lock;lock.lock();try {// 如果隊列已滿,等待while (!linkFirst(node))notFull.await();} finally {lock.unlock();} }public void putLast(E e) throws InterruptedException {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);final ReentrantLock lock = this.lock;lock.lock();try {// 如果隊列已滿,等待while (!linkLast(node))notFull.await();} finally {lock.unlock();} }public boolean offerFirst(E e, long timeout, TimeUnit unit)throws InterruptedException {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);// 計算超時時間long nanos = unit.toNanos(timeout);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {// 如果隊列已滿,超時等待while (!linkFirst(node)) {if (nanos <= 0L)return false;nanos = notFull.awaitNanos(nanos);}return true;} finally {lock.unlock();} }public boolean offerLast(E e, long timeout, TimeUnit unit)throws InterruptedException {if (e == null) throw new NullPointerException();Node<E> node = new Node<E>(e);long nanos = unit.toNanos(timeout);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {while (!linkLast(node)) {if (nanos <= 0L)return false;nanos = notFull.awaitNanos(nanos);}return true;} finally {lock.unlock();} }

刪除操作

public E removeFirst() {// 復用poll操作E x = pollFirst();if (x == null) throw new NoSuchElementException();return x; }public E removeLast() {E x = pollLast();if (x == null) throw new NoSuchElementException();return x; }public E pollFirst() {final ReentrantLock lock = this.lock;lock.lock();try {// 獲取頭節點的值,并刪除它return unlinkFirst();} finally {lock.unlock();} }private E unlinkFirst() {// assert lock.isHeldByCurrentThread();// 如果隊列為空,返回nullNode<E> f = first;if (f == null)return null;// 重置頭節點Node<E> n = f.next;E item = f.item;f.item = null;f.next = f; // help GCfirst = n;if (n == null)last = null;elsen.prev = null;--count;// 喚醒等待插入的線程notFull.signal();return item; }public E pollLast() {final ReentrantLock lock = this.lock;lock.lock();try {return unlinkLast();} finally {lock.unlock();} }private E unlinkLast() {// assert lock.isHeldByCurrentThread();Node<E> l = last;// 隊列為空,返回nullif (l == null)return null;// 更新尾節點Node<E> p = l.prev;E item = l.item;l.item = null;l.prev = l; // help GClast = p;if (p == null)first = null;elsep.next = null;--count;notFull.signal();return item; }public E takeFirst() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lock();try {E x;// 如果隊列為空,等待while ( (x = unlinkFirst()) == null)notEmpty.await();return x;} finally {lock.unlock();} }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();} }public E pollFirst(long timeout, TimeUnit unit)throws InterruptedException {long nanos = unit.toNanos(timeout);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {E x;while ( (x = unlinkFirst()) == null) {if (nanos <= 0L)return null;nanos = notEmpty.awaitNanos(nanos);}return x;} finally {lock.unlock();} }public E pollLast(long timeout, TimeUnit unit)throws InterruptedException {long nanos = unit.toNanos(timeout);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {E x;while ( (x = unlinkLast()) == null) {if (nanos <= 0L)return null;nanos = notEmpty.awaitNanos(nanos);}return x;} finally {lock.unlock();} }

訪問操作

public E getFirst() {// 復用peek方法E x = peekFirst();if (x == null) throw new NoSuchElementException();return x; }public E getLast() {E x = peekLast();if (x == null) throw new NoSuchElementException();return x; }public E peekFirst() {final ReentrantLock lock = this.lock;lock.lock();try {// 如果隊列不為空,返回頭元素return (first == null) ? null : first.item;} finally {lock.unlock();} }public E peekLast() {final ReentrantLock lock = this.lock;lock.lock();try {// 如果隊列不為空,返回尾元素return (last == null) ? null : last.item;} finally {lock.unlock();} }

BlockingQueue

由于BlockingDeque繼承自BlockingQueue接口,所以需要實現BlockingQueue中的方法,具體只需要復用前面提到的方法即可。

public boolean add(E e) {addLast(e);return true; }public boolean offer(E e) {return offerLast(e); }public void put(E e) throws InterruptedException {putLast(e); }public boolean offer(E e, long timeout, TimeUnit unit)throws InterruptedException {return offerLast(e, timeout, unit); }public E remove() {return removeFirst(); }public E poll() {return pollFirst(); }public E take() throws InterruptedException {return takeFirst(); }public E poll(long timeout, TimeUnit unit) throws InterruptedException {return pollFirst(timeout, unit); }public E element() {return getFirst(); }public E peek() {return peekFirst(); }

核心要點

  • LinkedBlockingDeque 是基于鏈表的雙端阻塞隊列,線程安全,元素不允許為 null
  • 內部使用一個雙向鏈表
  • 可以在鏈表兩頭同時進行put和take操作,只能使用一個鎖
  • 插入線程在執行完操作后如果隊列未滿會喚醒其他等待插入的線程,同時隊列非空還會喚醒等待獲取元素的線程;take線程同理。
  • 迭代器與內部的雙向鏈表保持弱一致性,調用 remove(T) 方法刪除一個元素后,不會解除其對下一個結點的next引用,否則迭代器將無法工作。
  • 迭代器的forEachRemaining(Consumer<? super E> action)以64個元素為一批進行操作
  • forEach(Consumer<? super E> action),removeIf,removeAll,retainAll都是64個元素為一批進行操作

實戰

因為 LinkedBlockingDeque 取出是阻塞的,所以可以做一個 生產-消費 模型

package zyj;import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque;public class Product {//指定隊列最大值為100BlockingDeque<Apple> deque = new LinkedBlockingDeque(100);//生產,如果隊列滿了,則拋出 IllegalStateExceptionpublic void produce(Apple apple) {deque.push(apple);}//消費,如果隊列為空,則線程阻塞public Apple consume() {try {return deque.take();} catch (InterruptedException e) {e.printStackTrace();}return null;} }

總結

以上是生活随笔為你收集整理的Java阻塞队列 LinkedBlockingDeque的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。