面試--集合(四)併發集合框架阻塞佇列與非阻塞佇列
java語的框架父類介面是Iterable,從這個介面向下一一進行繼承。
一:集合架構的簡介
1:介面Iterable
主要用於迭代迴圈,僅有一個iterator()方法,通過返回Iterable物件,進行迴圈處理。
2:介面Collection
提供了集合框架最主要,最常用的操作,介面內部提供的主要方法是針對資料的怎刪改查操作。
3:介面list
介面list對Collection介面進行擴充套件,允許資料根據索引位置操作資料,並且內容允許重複。實現類ArrayList可以使陣列有序排序,但不是執行緒安全的,如果想使用執行緒安全的連結串列則可以使用Vector類,Vector類是執行緒安全的。
3:介面set
set也是對Collection進行擴充套件,它的特點是內容不允許重複,排序方式為自然排序,為了防止元素重複的原理使用的是元素重寫hashCode()和equals()方法,set的常用介面是不支援執行緒安全的HashSet.
二:非阻塞佇列
非阻塞佇列的特點是佇列裡面沒有資料時,操作佇列會返回異常或者null,不具有阻塞佇列的優點。常見的非阻塞佇列有:
ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentSkipListSet,ConcurrentLinkedQueue,ConcurrentLinkedDeque,
CopyOnWriteArrayList,CopyOnWriteArraySet.
1:ConcurrentHashMap的使用:
由於HashMap不是執行緒安全的,而HashTable是執行緒安全的,當多個執行緒呼叫iterator()方法返回iterator物件,再呼叫remove()方法時會出現異常,就是不支援Iterator併發的刪除。可以使用ConcurrentHashMap類。
ConcurrentHashMap支援迭代,但是不支援排序,如果排序可以使用LinkedHashMap,LinkedHashMap支援key的順序性,但是不支援併發。
2:ConcurrentSkipListMap的使用:
如果有要安全性又要排序就可以使用ConcurrentSkipListMap。
3:ConcurrentSkipListSet使用
ConcurrentSkipListMap類支援排序而且不允許重複的元素,
4:ConcurrentLinkedQueue的使用:
ConcurrentLinkedQueue類提供了併發環境的佇列操作,
方法poll()當前沒有獲得資料時返回null,如果有資料則移除表頭,並將表頭進行返回,
方法element()當前沒有獲取資料時出現NoSuchElementException異常,如果有資料則返回表頭項,
方法peek()當前沒有獲得發回資料時返回為null,有資料則 不移除表頭,並將表頭進行返回。
5:ConcurrentLinkedDeque的使用:
ConcurrentLinkedQueue僅支援對列頭進行操作,ConcurrentLinkedDeue支援對列頭和列尾雙向操作。
6:CopyOnWriteArrayList的使用:
支援執行緒安全,解決ArrayList執行緒不安全。
7:CopyOnWriteArraySet:
支援執行緒安全,解決hashSet執行緒不安全。
三:阻塞佇列https://blog.csdn.net/stafen1/article/category/6863952
http://ifeve.com/java-blocking-queue/ 併發程式設計網
阻塞佇列:如果佇列是空,從佇列取東西會被阻塞進入等待,直到佇列裡添加了元素才會被喚醒。如果是滿的佇列,一樣被阻塞。
JDK7提供了7個阻塞佇列。分別是
- ArrayBlockingQueue :一個由陣列結構組成的有界阻塞佇列。
- LinkedBlockingQueue :一個由連結串列結構組成的有界阻塞佇列。
- PriorityBlockingQueue :一個支援優先順序排序的無界阻塞佇列。
- DelayQueue:一個使用優先順序佇列實現的無界阻塞佇列。
- SynchronousQueue:一個不儲存元素的阻塞佇列。
- LinkedTransferQueue:一個由連結串列結構組成的無界阻塞佇列。
- LinkedBlockingDeque:一個由連結串列結構組成的雙向阻塞佇列。
1ArrayBlockingQueue
ArrayBlockingQueue是一個用陣列實現的有界阻塞佇列。此佇列按照先進先出(FIFO)的原則對元素進行排序。預設情況下不保證訪問者公平的訪問佇列,所謂公平訪問佇列是指阻塞的所有生產者執行緒或消費者執行緒,當佇列可用時,可以按照阻塞的先後順序訪問佇列,即先阻塞的生產者執行緒,可以先往佇列裡插入元素,先阻塞的消費者執行緒,可以先從佇列裡獲取元素。通常情況下為了保證公平性會降低吞吐量。我們可以使用以下程式碼建立一個公平的阻塞佇列:
1 |
ArrayBlockingQueue fairQueue = new ArrayBlockingQueue( 1000 , true ); |
訪問者的公平性是使用可重入鎖實現的,程式碼如下:
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
LinkedBlockingQueue
LinkedBlockingQueue和ArrayBlockingQueue類似,只不過LInkedBlockingQueue是無界的,也可以定義成一個有界的。
一個用連結串列實現的有界阻塞佇列。此佇列的預設和最大長度為Integer.MAX_VALUE。此佇列按照先進先出的原則對元素進行排序。
PriorityBlockingQueue
PriorityBlockingQueue是一個支援優先順序的無界佇列。預設情況下元素採取自然順序排列,也可以通過比較器comparator來指定元素的排序規則。元素按照升序排列。
SynchronousQueue
SynchronousQueue為非同步佇列,是一個不儲存元素的阻塞佇列。每一個put操作必須等待一個take操作,否則不能繼續新增元素。SynchronousQueue可以看成是一個傳球手,負責把生產者執行緒處理的資料直接傳遞給消費者執行緒。佇列本身並不儲存任何元素,非常適合於傳遞性場景,比如在一個執行緒中使用的資料,傳遞給另外一個執行緒使用,SynchronousQueue的吞吐量高於LinkedBlockingQueue 和 ArrayBlockingQueue。
DelayQueue
DelayQueue是一個支援延時獲取元素的無界阻塞佇列。佇列使用PriorityQueue來實現。佇列中的元素必須實現Delayed介面,在建立元素時可以指定多久才能從佇列中獲取當前元素。只有在延遲期滿時才能從佇列中提取元素。我們可以將DelayQueue運用在以下應用場景:
- 快取系統的設計:可以用DelayQueue儲存快取元素的有效期,使用一個執行緒迴圈查詢DelayQueue,一旦能從DelayQueue中獲取元素時,表示快取有效期到了。
- 定時任務排程。使用DelayQueue儲存當天將會執行的任務和執行時間,一旦從DelayQueue中獲取到任務就開始執行,從比如TimerQueue就是使用DelayQueue實現的。
佇列中的Delayed必須實現compareTo來指定元素的順序。比如讓延時時間最長的放在佇列的末尾。
LinkedTransferQueue
LinkedTransferQueue是一個由連結串列結構組成的無界阻塞TransferQueue佇列。相對於其他阻塞佇列LinkedTransferQueue多了tryTransfer和transfer方法。