java併發容器——延遲佇列DelayQueue
延時阻塞佇列DelayQueue是一種特殊的優先順序佇列,它也是無界的,它要求每個元素都實現Delayed介面,該介面的宣告為:
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
Delayed擴充套件了Comparable介面,也就是說,DelayQueue的每個元素都是可比較的,它有一個額外方法getDelay返回一個給定時間單位unit的整數,表示再延遲多長時間,如果小於等於0,表示不再延遲。
DelayQueue也是優先順序佇列,它按元素的延時時間出隊,它的特殊之處在於,只有當元素的延時過期之後才能被從佇列中拿走,也就是說,take方法總是返回第一個過期的元素,如果沒有,則阻塞等待。
DelayQueue可以用於實現定時任務,我們看段簡單的示例程式碼:
public class DelayedQueueDemo {
private static final AtomicLong taskSequencer = new AtomicLong(0);
static class DelayedTask implements Delayed {
private long runTime;
private long sequence;
private Runnable task;
public DelayedTask(int delayedSeconds, Runnable task) {
this.runTime = System.currentTimeMillis() + delayedSeconds * 1000;
this.sequence = taskSequencer.getAndIncrement();
this.task = task;
}
@Override
public int compareTo(Delayed o) {
if (o == this) {
return 0;
}
if (o instanceof DelayedTask) {
DelayedTask other = (DelayedTask) o;
if (runTime < other.runTime) {
return -1;
} else if (runTime > other.runTime) {
return 1;
} else if (sequence < other.sequence) {
return -1;
} else {
return 1;
}
}
throw new IllegalArgumentException();
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(runTime - System.currentTimeMillis(),
TimeUnit.MICROSECONDS);
}
public Runnable getTask() {
return task;
}
}
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayedTask> tasks = new DelayQueue<>();
tasks.put(new DelayedTask(2, new Runnable() {
@Override
public void run() {
System.out.println("execute delayed task");
}
}));
DelayedTask task = tasks.take();
task.getTask().run();
}
}
DelayedTask表示延時任務,只有延時過期後任務才會執行,任務按延時時間排序,延時一樣的按照入隊順序排序。
內部,DelayQueue是基於PriorityQueue實現的,它使用一個鎖ReentrantLock保護所有訪問,使用一個條件available表示頭部是否有元素,當頭部元素的延時未到時,take操作會根據延時計算需睡眠的時間,然後睡眠,如果在此過程中有新的元素入隊,且成為頭部元素,則阻塞睡眠的執行緒會被提前喚醒然後重新檢查。以上是基本思路,DelayQueue的實現有一些優化,以減少不必要的喚醒,具體我們就不探討了。
模擬一個考試的日子,考試時間為120分鐘,30分鐘後才可交卷,當時間到了,或學生都交完捲了考試結束。
這個場景中幾個點需要注意:
- 考試時間為120分鐘,30分鐘後才可交卷,初始化考生完成試卷時間最小應為30分鐘
- 對於能夠在120分鐘內交卷的考生,如何實現這些考生交卷
- 對於120分鐘內沒有完成考試的考生,在120分鐘考試時間到後需要讓他們強制交卷
- 在所有的考生都交完卷後,需要將控制執行緒關閉
抽象出兩個類,學生類和老師類,用DelayQueue儲存考生(Student類)。每一個考生都有自己的名字和完成試卷的時間
Teacher執行緒對DelayQueue進行監控,收取完成試卷小於120分鐘的學生的試卷。當考試時間120分鐘到時,teacher執行緒宣佈考試結束,強制DelayQueue中還存在的考生交卷。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
相關推薦java併發容器——延遲佇列DelayQueue延時阻塞佇列DelayQueue是一種特殊的優先順序佇列,它也是無界的,它要求每個元素都實現Delayed介面,該介面的宣告為: public interface Delayed extends Comparable<Delayed> { 併發佇列-無界阻塞延遲佇列DelayQueue原理探究一、前言 DelayQueue佇列中每個元素都有個過期時間,並且佇列是個優先順序佇列,當從佇列獲取元素時候,只有過期元素才會出佇列。 二、 DelayQueue類圖結構 如圖DelayQueue中內部使用的是PriorityQueue存放資料,使用ReentrantLock實現執行緒同步, 【Java】延遲佇列DelayQueue裡的坑 concurrent.Delayed使用延遲佇列需要實現Delayed介面 重要的是此介面方法 @Override public long getDelay(TimeUnit unit) { System.err Java同步佇列(非阻塞佇列與阻塞佇列)——java併發容器在併發程式設計中,有時候需要使用執行緒安全的佇列。如果要實現一個執行緒安全的佇列有兩種方式:一種是使用阻塞演算法,另一種是使用非阻塞演算法。 使用阻塞演算法的佇列可以用一個鎖(入隊和出隊用同一把鎖)或兩個鎖(入隊和出隊用不同的鎖)等方式來實現。 非阻塞的實現方式則可以使用 Java併發容器詳細介紹概述 java.util包中的大部分容器都是非執行緒安全的,若要在多執行緒中使用容器,你可以使用Collections提供的包裝函式:synchronizedXXX,將普通容器變成執行緒安全的容器。但該方法僅僅是簡單地給容器使用同步,效率很 Java併發容器:ConcurrentLinkedQueue轉自:https://blog.csdn.net/chenssy/article/details/74853120 http://cmsblogs.com/ 要實現一個執行緒安全的佇列有兩種方式:阻塞和非阻塞。阻塞佇列無非就是鎖的應用,而非阻塞則是CAS演算法的應用。下面我們就開始一個非 延遲佇列DelayQueue簡單入門一、DelayQueue是什麼 DelayQueue是一個無界的BlockingQueue,用於放置實現了Delayed介面的物件,其中的物件只能在其到期時才能從佇列中取走。這種佇列是有序的,即隊頭物件的延遲到期時間最長。注意:不能將null元素放置到這種佇列中。 二、Delay JAVA併發容器:ConcurrentSkipListMap生活 目標定下來以後就不要去變,只要確定是對的,總可以到達。 二分查詢 二分查詢要求有序性,為了保障可以隨機訪問,因此會把資料儲存在連續的記憶體中,在查詢的時候效率高,但是在增加和刪除時需要大量移動元素以保證有序,所以效率不高。 如果需要快速的二分查詢,又要兼顧刪除增加元素的效率 JAVA併發容器:CopyOnWriteArrayList與CopyOnWriteArraySet生活 所有的程式設計師都劇作家,而所有計算機都是糟糕的演員。 CopyOnWriteArrayList介紹 還記得學集合的時候,學的第一個集合就是ArrayList.它是一個由陣列實現的集合。因為他對陣列的增刪改和查詢都是不加鎖的,所以它並不是執行緒安全的。 因此,我們會引入到一 JAVA併發容器:JDK1.7 與 1.8 ConcurrentHashMap 區別生活 為什麼我們總是沒有時間把事情做對,卻有時間做完它? 瞭解ConcurrentHashMap 工作中常用到hashMap,但是HashMap在多執行緒高併發場景下並不是執行緒安全的。 所以引入了ConcurrentHashMap,它是HashMap的執行緒安全版本,採用了分段 java併發包訊息佇列及在開源軟體中的應用1.BlockingQueue的常用方法 BlockingQueue也是java.util.concurrent下的主要用來控制執行緒同步的工具。 主要的方法是:put、take一對阻塞存取;add、poll一對非阻塞存取。 插入: 1 java 併發容器解決併發情況下的容器執行緒安全問題的。給多執行緒環境準備一個執行緒安全的容器物件。 執行緒安全的容器物件: Vector, Hashtable。執行緒安全容器物件,都是使用 synchronized 方法實現的。 concurrent 包中的同步容器,大多數是使 JAVA併發容器:為什麼說ConcurrentHashMap是弱一致性的?ConcurrentHashMap的弱一致性體現在clear、迭代器和get方法,原因在於沒有加鎖。 舉例: 迭代器在遍歷資料的時候是一個Segment一個Segment去遍歷的,如果在遍歷完一個Segment時正好有一個執行緒在剛遍歷完的Segment上插入資料,就會體現出不一致性。 cl 深入剖析java併發之阻塞佇列LinkedBlockingQueue與ArrayBlockingQueue關聯文章: 深入理解Java型別資訊(Class物件)與反射機制 深入理解Java列舉型別(enum) 深入理解Java註解型別(@Annotation) 深入理解Java類載入器(ClassLoader) 深入理解Java併發之synchronized實現原理 java併發包訊息佇列訊息佇列常用於有生產者和消費者兩類角色的多執行緒同步場景BlockingQueue也是java.util.concurrent下的主要用來控制執行緒同步的工具。主要的方法是:put、take一對阻塞存取;add、poll一對非阻塞存取。 插入: 【搞定Java併發程式設計】第21篇:Java併發容器之ConcurrentHashMap詳解上一篇:讀寫鎖 --- ReentrantReadWriteLock詳解 本文目錄: 1、為什麼要使用ConcurrentHashMap? 2、ConcurrentHashMap的實現 2.1、ConcurrentHashMap中主要的成員變數、成員方法和內部類 2.2、分段鎖的 java併發程式設計——阻塞佇列與非阻塞佇列ArrayBlockingQueue ArrayBlockingQueue是一個有界阻塞佇列,資料結構基於陣列、使用ReentrantLock、Condition保證併發同步。 所謂阻塞佇列 當佇列滿了,則會對生產執行緒產生阻塞直到有空位可插入; 當佇列 Java併發容器ConcurrentHashMap原理及HashMap死迴圈原因的分析HashMap是我們最常用的資料結構之一,它方便高效,但遺憾的是,HashMap是執行緒不安全的,在併發環境下,在HashMap的擴容過程中,可能造成散列表的迴圈鎖死。而執行緒安全的HashTable使用了大量Synchronized鎖,導致了效率非常低下。幸運的是,併發程 Java高併發程式設計(八):Java併發容器和框架1. ConcurrentHashMap 1.1 ConcurrentHashMap的優勢 在併發程式設計中使用HashMap可能導致程式死迴圈。而使用執行緒安全的HashTable效率又非 常低下,基於以上兩個原因,便有了ConcurrentHashMap的登場機會。 java併發程式設計條件佇列的喚醒機制探究bf1,bf2是兩個大小各為3的條件佇列。3將要put進bf1,此時因為bf1已滿而已呼叫wait()方法掛起執行緒,此時若對bf2()執行take()方法並呼叫notifyall()是否會喚醒wait()中的bf1?(對兩個佇列的操作存在於兩個不同的執行緒 |