1. 類的定義
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer
implements java.io.Serializable
複製程式碼
從類的定義中可以看出
- AbstractQueuedSynchronizer 是一個抽象類,使用了模板方法設計模式(實現了大部分功能,極少部分讓子類實現)
- AbstractQueuedSynchronizer 繼承了 AbstractOwnableSynchronizer
- AbstractOwnableSynchronizer 實現了java.io.Serializable介面,表示AbstractQueuedSynchronizer支援序列化
2. 欄位屬性
//序列化版本號
private static final long serialVersionUID = 7373984972572414691L;
//等待佇列的頭,延遲初始化。 僅在初始化時,使用setHead修改。 注意:如果頭存在,其等待狀態保證不會被取消
private transient volatile Node head;
//等待佇列的尾部,延遲初始化
private transient volatile Node tail;
//同步狀態, 0(預設初始值)表示沒有鎖,1表示上鎖,可以大於1表示重入鎖,有的初始值為-1
//state使用volatile修飾
private volatile int state;
複製程式碼
從欄位屬性可以看出
- AbstractQueuedSynchronizer內部維護了一個連結串列佇列
- AbstractQueuedSynchronizer儲存了鎖的狀態state
3. 構造方法
//預設空的建構函式,沒有任何操作
protected AbstractQueuedSynchronizer() { }
複製程式碼
從構造方法可以看出
- AbstractQueuedSynchronizer的構造方法使用protected修飾,是一個空的建構函式,需要子類自己實現
4. 方法
getState 方法
//獲取當前的同步狀態
protected final int getState() {
return state;
}
複製程式碼
setState 方法
//設定當前的同步狀態
protected final void setState(int newState) {
state = newState;
}
複製程式碼
compareAndSetState 方法
//使用CAS設定同步狀態
protected final boolean compareAndSetState(int expect, int update) {
//使用Unsafe的compareAndSwapInt方法更新同步狀態,這是一個native方法
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
複製程式碼
enq 方法
//新增節點到隊尾
private Node enq(final Node node) {
//for無限迴圈,重試CAS
for (;;) {
//如果佇列尾節點
Node t = tail;
if (t == null) { // Must initialize
//如果尾節點為null,進行初始化
//CAS設定一個新建立的節點為頭節點,有可能其它執行緒先建立成功
if (compareAndSetHead(new Node()))
//建立頭節點成功,把尾節點指向頭節點
tail = head;
} else {
//如果尾節點不為null
//把加入的節點前驅結點的引用指向尾節點
node.prev = t;
//CAS設定node為尾節點,有可能其它節點也在設定尾節點,可能會失敗,然後重試
if (compareAndSetTail(t, node)) {
//如果新增成功
//把前驅節點的後驅的引用指向加入的節點
t.next = node;
//返回加入節點的前驅節點(可能是以前的尾節點,其它執行緒可能會修改它)
return t;
}
}
}
}
複製程式碼
compareAndSetHead 方法
//設定頭節點,只在enq方法中呼叫
private final boolean compareAndSetHead(Node update) {
//如果頭節點為null,才把傳入的節點設定為頭節點
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
複製程式碼
compareAndSetTail 方法
//設定尾節點,只在enq方法中呼叫
private final boolean compareAndSetTail(Node expect, Node update) {
//如果尾節點為expect,才把傳入的節點設定為尾節點
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
複製程式碼
addWaiter 方法
//新增節點到隊尾
private Node addWaiter(Node mode) {
//使用當前執行緒和傳入節點建立新的節點,後面新增的是這個新建立的節點
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//獲取尾節點的副本
Node pred = tail;
if (pred != null) {
//如果尾節點不為null
//把新增節點的前驅結點引用指向尾節點
node.prev = pred;
//CAS設定node為尾節點,有可能其它節點也在設定尾節點,可能會失敗,然後重試
if (compareAndSetTail(pred, node)) {
//把前驅節點的後驅節點的引用指向加入的節點
pred.next = node;
//返回加入節點的前驅節點(可能是以前的尾節點,其它執行緒可能會修改它)
return node;
}
}
//如果尾節點為null,或者被其它執行緒先新增成功
//使用enq方法新增
enq(node);
return node;
}
複製程式碼
setHead 方法
//設定頭節點,僅由acquire方法呼叫
private void setHead(Node node) {
//把頭節點指向傳入的節點
head = node;
//把傳入節點的thread置為null
node.thread = null;
//把傳入節點的prev置為null
node.prev = null;
}
複製程式碼
unparkSuccessor 方法
//如果有節點退出,喚醒佇列下一個未被取消節點的執行緒執行
//注意,這個node引數是頭節點
private void unparkSuccessor(Node node) {
//獲取頭節點的waitStatus,waitStatus大於0表示被取消
int ws = node.waitStatus;
if (ws < 0)
//如果頭節點的waitStatus小於0, 把頭節點的waitStatus設定為0
compareAndSetWaitStatus(node, ws, 0);
//獲取頭節的後驅節點
Node s = node.next;
if (s == null || s.waitStatus > 0) {
//如果後驅節點為nul 或者 後驅節點的waitStatus大於0(被取消)
s = null;
//使用for迴圈從尾節點開始往前遍歷
//找到遍歷的第一個waitStatus小於等於0(未被取消)的節點
//注意,找到的是順序的第一個,不是倒序的第一個,這個會一直迴圈到頭節點
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
//如果節點不為null, 喚醒節點的執行緒
LockSupport.unpark(s.thread);
}
複製程式碼
doReleaseShared 方法
//共享模式下的訊號釋放
private void doReleaseShared() {
/*
* Ensure that a release propagates, even if there are other
* in-progress acquires/releases. This proceeds in the usual
* way of trying to unparkSuccessor of head if it needs
* signal. But if it does not, status is set to PROPAGATE to
* ensure that upon release, propagation continues.
* Additionally, we must loop in case a new node is added
* while we are doing this. Also, unlike other uses of
* unparkSuccessor, we need to know if CAS to reset status
* fails, if so rechecking.
*/
//for無限迴圈
for (;;) {
//獲取頭節點的副本
Node h = head;
if (h != null && h != tail) {
//如果h節點不為null 並且 h節點不等於尾節點(佇列中有元素)
//獲取h節點的waitStatus
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
//如果h節點的狀態為-1
//把h節點的waitStatus設定為0
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
//如果失敗進行下一次迴圈(繼續操作)
continue; // loop to recheck cases
//如果設定成功,喚醒h的後驅節點,頭節點的狀態可能會改變
unparkSuccessor(h);
}
//如果h節點的狀態為0 並且 CAS設定節點的waitStatus為-3失敗的話進行下一次迴圈
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
//如果h節點為頭節點中斷迴圈,如果head改變則繼續迴圈
break;
}
}
複製程式碼
setHeadAndPropagate 方法
//設定佇列頭和傳播方式
private void setHeadAndPropagate(Node node, int propagate) {
//獲取頭節點的副本
Node h = head; // Record old head for check below
//把傳入的節點設定為頭節點
setHead(node);
/*
* Try to signal next queued node if:
* Propagation was indicated by caller,
* or was recorded (as h.waitStatus either before
* or after setHead) by a previous operation
* (note: this uses sign-check of waitStatus because
* PROPAGATE status may transition to SIGNAL.)
* and
* The next node is waiting in shared mode,
* or we don't know, because it appears null
*
* The conservatism in both of these checks may cause
* unnecessary wake-ups, but only when there are multiple
* racing acquires/releases, so most need signals now or soon
* anyway.
*/
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
//如果傳入的傳播方式大於0
//如果頭節點為null
//如果頭節點的waitStatus小於0
//如果node為null
//如果node的waitStatus小於0
//獲取node的後驅節點
Node s = node.next;
if (s == null || s.isShared())
//如果後驅節點為null 或者 後驅節點是共享模式
//釋放共享模式下的訊號
doReleaseShared();
}
}
複製程式碼
cancelAcquire 方法
//取消節點獲取鎖的嘗試
private void cancelAcquire(Node node) {
if (node == null)
//如果node為null,直接返回
return;
//把node的執行緒置為null
node.thread = null;
//獲取node的前一個節點
Node pred = node.prev;
//while迴圈,如果前驅結點的waitStatus大於0(被取消),一直往上找
//找到前面第一個未被取消的節點
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
//獲取前驅結點的後驅節點
Node predNext = pred.next;
//把node節點的waitStatus設定為取消狀態
node.waitStatus = Node.CANCELLED;
// 如果當前節點是尾節點,移除自己,把前驅結點設定為尾節點
if (node == tail && compareAndSetTail(node, pred)) {
//把前驅節點的後驅節點設定為null
compareAndSetNext(pred, predNext, null);
} else {
//node不是尾節點的情況
//If successor needs signal, try to set pred's next-link
//so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
//喚醒前驅結點
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
複製程式碼
shouldParkAfterFailedAcquire 方法
//當前執行緒沒有獲取到鎖,是否需要掛起執行緒
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
//獲取前驅結點的waitStatus
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
//前驅節點的waitStatus為-1,說明前驅結點狀態正常,可以安全的掛起當前執行緒,直接返回true
return true;
if (ws > 0) {
//如果前驅結點的waitStatus大於0,表示前驅結點取消了排隊
//注意:進入阻塞佇列排隊的執行緒會被掛起,而喚醒的操作是由前驅節點完成的
//往前一直找,直到找到waitStatus大於等於0的節點作為node節點的前驅節點
//node的執行緒掛起以後後面要靠找到的前驅節點來喚醒
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
//前驅節點的waitStatus不等於1和-1,只能等於0,-2, -3
//把前驅節點的waitStatus設定為-1
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
//返回false表示不需要掛起
return false;
}
複製程式碼
selfInterrupt 方法
//中斷當前執行緒
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
複製程式碼
parkAndCheckInterrupt 方法
//掛起當前執行緒,並檢查是否中斷
private final boolean parkAndCheckInterrupt() {
//掛起當前執行緒
LockSupport.park(this);
//檢查當前執行緒是否中斷
return Thread.interrupted();
}
複製程式碼
acquireQueued 方法
//嘗試獲取鎖,失敗的話就中斷等著前驅節點喚醒自己
final boolean acquireQueued(final Node node, int arg) {
//預設失敗
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
//獲取node的前驅結點
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
//如果p為頭節點 並且 獲取鎖成功
//把node設定為頭節點
setHead(node);
//把前驅結點的後驅節點置為null
p.next = null; // help GC
//設定為成功標誌
failed = false;
//返回interrupted標誌
return interrupted;
}
//找到能夠喚醒自己的前驅節點,然後中斷在這等著喚醒
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//如果node需要被掛起
//interrupted標誌置為true
interrupted = true;
}
} finally {
if (failed)
//如果失敗,取消node獲取鎖的嘗試
cancelAcquire(node);
}
}
複製程式碼
doAcquireInterruptibly 方法
//獲取獨佔鎖,如果獲取失敗,把執行緒掛起並丟擲異常
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
//新增獨佔模式節點到隊尾
final Node node = addWaiter(Node.EXCLUSIVE);
//設定失敗標誌為true
boolean failed = true;
try {
for (;;) {
//獲取node的前驅節點
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
//如果node的前驅節點是頭結點,並且獲取鎖成功
//把node設定為頭結點
setHead(node);
//把前驅節點的後驅節點引用置為null
p.next = null; // help GC
//設定失敗標誌為false
failed = false;
//直接返回
return;
}
//如果沒獲取到鎖,把執行緒掛起
//如果掛起執行緒失敗,丟擲異常
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
//失敗,取消node獲取鎖的嘗試
cancelAcquire(node);
}
}
複製程式碼
doAcquireNanos 方法
//獲取獨佔鎖, 指定超時時間
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
//引數檢查
if (nanosTimeout <= 0L)
return false;
//計算過期時間
final long deadline = System.nanoTime() + nanosTimeout;
//新增獨佔模式節點到隊尾
final Node node = addWaiter(Node.EXCLUSIVE);
//設定失敗標誌為true
boolean failed = true;
try {
//for無限迴圈
for (;;) {
//獲取node的前驅節點
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
//如果node的前驅節點是頭結點,並且獲取鎖成功
//把node設定為頭結點
setHead(node);
//把前驅節點的後驅節點引用置為null
p.next = null; // help GC
//設定失敗標誌為false
failed = false;
//獲取鎖成功,返回true
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
//超時,返回false
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
//如果沒獲取到鎖,把執行緒掛起
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
//如果執行緒被中斷,丟擲異常
throw new InterruptedException();
}
} finally {
if (failed)
//失敗,取消node獲取鎖的嘗試
cancelAcquire(node);
}
}
複製程式碼
doAcquireShared 方法
//獲取共享鎖
private void doAcquireShared(int arg) {
//新增共享模式節點到隊尾
final Node node = addWaiter(Node.SHARED);
//設定失敗標誌為true
boolean failed = true;
try {
//設定中斷標誌為true
boolean interrupted = false;
//for無限迴圈
for (;;) {
//獲取node的前驅節點
final Node p = node.predecessor();
if (p == head) {
//如果前驅節點是頭結點
//嘗試獲取共享鎖
int r = tryAcquireShared(arg);
if (r >= 0) {
//獲取成功,設定頭結點為node節點, 並繼續傳播
setHeadAndPropagate(node, r);
//設定前驅節點的後驅節點引用置為null
p.next = null; // help GC
if (interrupted)
//如果中斷標誌為true,中斷當前執行緒
selfInterrupt();
//設定失敗標誌為false
failed = false;
//直接返回
return;
}
}
//如果沒獲取到鎖,把執行緒掛起
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//掛起執行緒成功,設定中斷標誌為true
interrupted = true;
}
} finally {
if (failed)
//失敗,取消node獲取鎖的嘗試
cancelAcquire(node);
}
}
複製程式碼
doAcquireSharedInterruptibly 方法
//獲取共享鎖
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
//新增共享模式節點到隊尾
final Node node = addWaiter(Node.SHARED);
//設定失敗標誌為true
boolean failed = true;
try {
//for無限迴圈
for (;;) {
//獲取node的前驅節點
final Node p = node.predecessor();
if (p == head) {
//如果前驅節點是頭結點
//嘗試獲取共享鎖
int r = tryAcquireShared(arg);
if (r >= 0) {
//獲取成功,設定頭結點為node節點, 並繼續傳播
setHeadAndPropagate(node, r);
//設定前驅節點的後驅節點引用置為null
p.next = null; // help GC
//設定失敗標誌為false
failed = false;
//直接返回
return;
}
}
//如果沒獲取到鎖,把執行緒掛起
//如果掛起執行緒失敗,丟擲異常
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
//失敗,取消node獲取鎖的嘗試
cancelAcquire(node);
}
}
複製程式碼
doAcquireSharedNanos 方法
//獲取共享鎖,指定超時時間
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
//引數檢查
if (nanosTimeout <= 0L)
return false;
//計算過期時間
final long deadline = System.nanoTime() + nanosTimeout;
//新增共享模式節點到隊尾
final Node node = addWaiter(Node.SHARED);
//設定失敗標誌為true
boolean failed = true;
try {
//for無限迴圈
for (;;) {
//獲取node的前驅節點
final Node p = node.predecessor();
if (p == head) {
//如果前驅節點是頭結點
//嘗試獲取共享鎖
int r = tryAcquireShared(arg);
if (r >= 0) {
//獲取成功,設定頭結點為node節點, 並繼續傳播
setHeadAndPropagate(node, r);
//設定前驅節點的後驅節點引用置為null
p.next = null; // help GC
//設定失敗標誌為false
failed = false;
//直接返回
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
//超時,返回false
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
//如果沒獲取到鎖,把執行緒掛起
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
//如果執行緒被中斷,丟擲異常
throw new InterruptedException();
}
} finally {
if (failed)
//失敗,取消node獲取鎖的嘗試
cancelAcquire(node);
}
}
複製程式碼
tryAcquire 方法
//嘗試獲取獨佔鎖,強制子類實現
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
複製程式碼
tryRelease 方法
//嘗試釋放鎖,強制子類實現
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
複製程式碼
tryAcquireShared 方法
//嘗試獲取共享鎖,強制子類實現
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
複製程式碼
tryReleaseShared 方法
//嘗試釋放共享鎖,強制子類實現
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
複製程式碼
isHeldExclusively 方法
//返回鎖的模式, true 獨佔鎖
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
複製程式碼
acquire 方法
//獨佔模式獲取鎖
public final void acquire(int arg) {
//先嚐試獲取鎖,如果失敗,以獨佔模式新增到隊尾,中斷當前執行緒等著被喚醒
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
複製程式碼
acquireInterruptibly 方法
//獨佔模式獲取鎖,獲取失敗丟擲異常
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (!tryAcquire(arg))
doAcquireInterruptibly(arg);
}
複製程式碼
tryAcquireNanos 方法
//獨佔模式獲取鎖,設定超時時間
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
複製程式碼
release 方法
//釋放獨佔鎖
public final boolean release(int arg) {
if (tryRelease(arg)) {
//釋放獨佔鎖成功
//拷貝頭節點的副本
Node h = head;
if (h != null && h.waitStatus != 0)
//如果頭節點不為null 並且 頭節點的狀態正常
//喚醒下一個節點
unparkSuccessor(h);
return true;
}
return false;
}
複製程式碼
acquireShared 方法
//共享模式獲取鎖
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
複製程式碼
acquireSharedInterruptibly 方法
//共享模式獲取鎖,獲取失敗丟擲異常
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
複製程式碼
tryAcquireSharedNanos 方法
//共享模式獲取鎖,設定超時時間
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
複製程式碼
releaseShared 方法
//釋放共享鎖
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
複製程式碼
hasQueuedThreads 方法
//佇列中是否含有執行緒
public final boolean hasQueuedThreads() {
return head != tail;
}
複製程式碼
hasContended 方法
//當前是否有執行緒在使用鎖
public final boolean hasContended() {
return head != null;
}
複製程式碼
getFirstQueuedThread 方法
//獲取佇列中第一個執行緒(等待時間最長的執行緒)
public final Thread getFirstQueuedThread() {
// handle only fast path, else relay
//為空的話返回null
//呼叫fullGetFirstQueuedThread方法返回佇列中第一個執行緒
return (head == tail) ? null : fullGetFirstQueuedThread();
}
複製程式碼
fullGetFirstQueuedThread 方法
//獲取佇列中第一個執行緒
private Thread fullGetFirstQueuedThread() {
//一般情況下,head的後驅節點就是佇列中的第一個元素
//如果head不為null,並且head的後驅節點不為null,並且head的後驅節點的前驅節點是head節點
//直接返回head的後驅節點
Node h, s;
Thread st;
if (((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null) ||
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null))
return st;
//有可能還沒來的及設定head的後驅節點(多個執行緒操作)
//這種情況下,從tail往前找
Node t = tail;
Thread firstThread = null;
while (t != null && t != head) {
Thread tt = t.thread;
if (tt != null)
firstThread = tt;
t = t.prev;
}
return firstThread;
}
複製程式碼
isQueued 方法
//檢視給定執行緒是否正在排隊
public final boolean isQueued(Thread thread) {
if (thread == null)
throw new NullPointerException();
//for迴圈遍歷,從tail往前找
for (Node p = tail; p != null; p = p.prev)
if (p.thread == thread)
return true;
return false;
}
複製程式碼
getQueueLength 方法
//獲取佇列的長度
public final int getQueueLength() {
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
}
複製程式碼
getQueuedThreads 方法
//獲取佇列中的所有執行緒,以集合的方式返回
public final Collection<Thread> getQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
複製程式碼
getExclusiveQueuedThreads 方法
//獲取佇列中的所有獨佔模式的執行緒,以集合的方式返回
public final Collection<Thread> getExclusiveQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
複製程式碼
getSharedQueuedThreads 方法
//獲取佇列中的所有共享模式的執行緒,以集合的方式返回
public final Collection<Thread> getSharedQueuedThreads() {
ArrayList<Thread> list = new ArrayList<Thread>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
複製程式碼