一個排序的有界的併發Buffer佇列Java實現
Java中使用TreeSet作為排序佇列或Buffer,而ConcurrentSkipListSet是支援併發的佇列,如果我們需要一個能實時排序又支援併發的佇列或Buffer怎麼辦?
設想一個場景,當我們不斷加入元素到集合,等所有元素都加入完畢後,我們只需要獲得排序的前5個元素,比如我們對半年內所有帖子或文章根據點贊量獲得前五篇點贊量最多的文章,首先我們需要將半年所有文章加入一個集合,這個集合是根據點贊量排序的,新增完畢後,我們需要獲得排名前5篇文章。
這可以透過JDK提供的 NavigableSet實現:
但是這種集合是無界的,它需要保留所有元素,其實有時這是沒有必要的,因為我們只感興趣所有元素中子集的子集,也就是說沒有必要從資料庫中獲得所有結果。
有沒有更好的資料結構能實現有界而且像以前能夠排序呢?實際是某種BoundedNavigableSet. 而且需要支援併發訪問,多個生產者可以同時將元素放入其中。
這種資料結構能夠在分散式查詢聚合實現中非常方便,特別是對分散式key-value資料庫如Cassandra, 基於多個分割槽查詢獲得的結果需要收集融合在一起。
下面是使用AtomicReferenceArray實現的無鎖演算法插入:
Compare 和 swap也是一個原子操作:
removal操作也應該是原子的:
完整原始碼見:Github
設想一個場景,當我們不斷加入元素到集合,等所有元素都加入完畢後,我們只需要獲得排序的前5個元素,比如我們對半年內所有帖子或文章根據點贊量獲得前五篇點贊量最多的文章,首先我們需要將半年所有文章加入一個集合,這個集合是根據點贊量排序的,新增完畢後,我們需要獲得排名前5篇文章。
這可以透過JDK提供的 NavigableSet實現:
NavigableSet<Integer> aSet = new TreeSet<>(); aSet.add(5); //..add more elements aSet.pollFirst();//'0'th aSet.pollFirst();//'1'th aSet = aSet.descendingSet(); aSet.pollFirst();//'n'th aSet.pollFirst();//'n-1'th <p class="indent"> |
但是這種集合是無界的,它需要保留所有元素,其實有時這是沒有必要的,因為我們只感興趣所有元素中子集的子集,也就是說沒有必要從資料庫中獲得所有結果。
有沒有更好的資料結構能實現有界而且像以前能夠排序呢?實際是某種BoundedNavigableSet. 而且需要支援併發訪問,多個生產者可以同時將元素放入其中。
這種資料結構能夠在分散式查詢聚合實現中非常方便,特別是對分散式key-value資料庫如Cassandra, 基於多個分割槽查詢獲得的結果需要收集融合在一起。
下面是使用AtomicReferenceArray實現的無鎖演算法插入:
/* Scan the array from given offset to 'insert' the item at a proper sort level */ boolean addItem(int fromOffset, T item) { for (int i = fromOffset; i < size(); i++) { // if there is no element at 'i'th position // set item at 'i' if (!buffer.compareAndSet(i, null, item)) { // compare and swap using Comparator provided // or, if element implements Comparable T swapped = compareAndSwap(i, item); if (swapped != null) { // the item has been placed. so break. but then // the element currently at 'i' has been swapped. so find its new // position, if present // we could have scanned from the 'i+1'th position, but to be safe // just in case some other element higher up was removed and this // needs to go up in that case if (i + 1 < size()) { addItem(0, swapped); } return true; } } else { return true; } } return false; } <p class="indent"> |
Compare 和 swap也是一個原子操作:
private T compareAndSwap(int i, T item) { boolean set = false, greater = false; T t = null; while (!set) { t = buffer.get(i); // either i-th element was replaced with this item // or by some other element // compare using Comparator/Comparable greater = compare(item, t) > 0; set = buffer.compareAndSet(i, t, greater ? item : t); } return greater ? t : null; } <p class="indent"> |
removal操作也應該是原子的:
public boolean remove(Object o) { T b; if(o == null) return false; for (int i = 0; i < size(); i++) { b = buffer.get(i); if (o.equals(b)) { if(buffer.compareAndSet(i, b, null)) { //shift left elements for (int j = i + i; j < size(); j++) { //check position form start. it can be possible that another higher item has been removed in the meantime addItem(0, buffer.get(j)); } return true; } } } return false; } <p class="indent"> |
完整原始碼見:Github
[該貼被banq於2015-12-30 11:25修改過]
相關文章
- C#實現一個萬物皆可排序的佇列C#排序佇列
- Java併發佇列與容器Java佇列
- 佇列的併發使用佇列
- 歸併排序與快速排序的一個實現與理解排序
- 佇列的一種實現:迴圈佇列佇列
- 透徹理解Java併發的等待佇列——ConditionJava佇列
- 解讀 Java 併發佇列 BlockingQueueJava佇列BloC
- Java併發系列 — 阻塞佇列(BlockingQueue)Java佇列BloC
- Java併發——阻塞佇列集(上)Java佇列
- Java併發——阻塞佇列集(下)Java佇列
- Java中幾個常用併發佇列比較 | BaeldungJava佇列
- 刷題系列 - 合併兩個順序佇列為一個新的佇列佇列
- 圖解--佇列、併發佇列圖解佇列
- 【資料結構】佇列(順序佇列、鏈佇列)的JAVA程式碼實現資料結構佇列Java
- JAVA併發之阻塞佇列淺析Java佇列
- Java併發程式設計——阻塞佇列Java程式設計佇列
- Java併發程式設計:阻塞佇列Java程式設計佇列
- 效能優化-使用雙buffer實現無鎖佇列優化佇列
- 阻塞佇列一——java中的阻塞佇列佇列Java
- 10分鐘搞定 Java 併發佇列好嗎?好的Java佇列
- golang實現併發爬蟲三(用佇列排程器實現)Golang爬蟲佇列
- Java併發6:阻塞佇列,Fork/Join框架Java佇列框架
- 乾貨|解讀Java併發佇列BlockingQueueJava佇列BloC
- Java併發包原始碼學習系列:阻塞佇列BlockingQueue及實現原理分析Java原始碼佇列BloC
- 自己動手實現一個阻塞佇列佇列
- Python佇列的三種佇列實現方法Python佇列
- Java併發指南11:解讀 Java 阻塞佇列 BlockingQueueJava佇列BloC
- Java 阻塞佇列(BlockingQueue)的內部實現原理Java佇列BloC
- 兩個棧實現佇列佇列
- 和朱曄一起復習Java併發(二):佇列Java佇列
- 【ZJOF】用來個棧來實現一個佇列佇列
- 【佇列】【懶排序】佇列Q佇列排序
- 陣列排序的實現陣列排序
- Java併發包原始碼學習系列:阻塞佇列實現之SynchronousQueue原始碼解析Java原始碼佇列
- Java併發包原始碼學習系列:阻塞佇列實現之LinkedTransferQueue原始碼解析Java原始碼佇列
- Java併發包原始碼學習系列:阻塞佇列實現之LinkedBlockingDeque原始碼解析Java原始碼佇列BloC
- Java併發包原始碼學習系列:阻塞佇列實現之LinkedBlockingQueue原始碼解析Java原始碼佇列BloC
- Java併發包原始碼學習系列:阻塞佇列實現之PriorityBlockingQueue原始碼解析Java原始碼佇列BloC
- Java併發包原始碼學習系列:阻塞佇列實現之DelayQueue原始碼解析Java原始碼佇列