|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
java.lang.Object java.util.concurrent.Semaphore
public class Semaphore
一個計數信號量。從概念上講,信號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire()
,然後再獲取該許可。每個 release()
添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可物件,Semaphore
只對可用許可的號碼進行計數,並採取相應的行動。
Semaphore 通常用於限制可以存取某些資源(物理或邏輯的)的執行緒數目。例如,下面的類別使用信號量控制對內容池的存取:
class Pool { private static final int MAX_AVAILABLE = 100; private final Semaphore available = new Semaphore(MAX_AVAILABLE, true); public Object getItem() throws InterruptedException { available.acquire(); return getNextAvailableItem(); } public void putItem(Object x) { if (markAsUnused(x)) available.release(); } // Not a particularly efficient data structure; just for demo protected Object[] items = ... whatever kinds of items being managed protected boolean[] used = new boolean[MAX_AVAILABLE]; protected synchronized Object getNextAvailableItem() { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (!used[i]) { used[i] = true; return items[i]; } } return null; // not reached } protected synchronized boolean markAsUnused(Object item) { for (int i = 0; i < MAX_AVAILABLE; ++i) { if (item == items[i]) { if (used[i]) { used[i] = false; return true; } else return false; } } return false; } }
獲得一項前,每個執行緒必須從信號量獲取許可,從而保證可以使用該項。該執行緒結束後,將項返回到池中並將許可返回到該信號量,從而允許其他執行緒獲取該項。注意,調用 acquire()
時無法保持同步鎖,因為這會阻止將項返回到池中。信號量封裝所需的同步,以限制對池的存取,這同維持該池本身一致性所需的同步是分開的。
將信號量初始化為 1,使得它在使用時最多只有一個可用的許可,從而可用作一個相互排斥的鎖。這通常也稱為二進制信號量,因為它只能有兩種狀態:一個可用的許可,或零個可用的許可。按此方式使用時,二進制信號量具有某種屬性(與很多 Lock
實作不同),即可以由執行緒釋放“鎖”,而不是由所有者(因為信號量沒有所有權的概念)。在某些專門的上下文(如死鎖恢復)中這會很有用。
此類別的建構子可選地接受一個公平 參數。當設置為 false 時,此類別不對執行緒獲取許可的順序做任何保證。特別地,闖入 是允許的,也就是說可以在已經等待的執行緒前為調用 acquire()
的執行緒分派一個許可,從邏輯上說,就是新執行緒將自己置於等待執行緒佇列的頭部。當公平設置為 true 時,信號量保證對於任何調用獲取
方法的執行緒而言,都按照處理它們調用這些方法的順序(即先進先出;FIFO)來選擇執行緒、獲得許可。注意,FIFO 排序必然應用到這些方法內的指定內部執行點。所以,可能某個執行緒先於另一個執行緒調用了 acquire
,但是卻在該執行緒之後到達排序點,並且從方法返回時也類似。還要注意,非同步的 tryAcquire
方法不使用公平設置,而是使用任意可用的許可。
通常,應該將用於控制資源存取的信號量初始化為公平的,以確保所有執行緒都可存取資源。為其他的種類別的同步控制使用信號量時,非公平排序的吞吐量優勢通常要比公平考慮更為重要。
此類別還提供便捷的方法來同時 acquire
和釋放
多個許可。小心,在未將公平設置為 true 時使用這些方法會增加不確定延期的風險。
記憶體一致性效果:執行緒中調用「釋放」方法(比如 release()
)之前的操作 happen-before 另一執行緒中緊跟在成功的「獲取」方法(比如 acquire()
)之後的操作。
建構子摘要 | |
---|---|
Semaphore(int permits)
創建具有給定的許可數和非公平的公平設置的 Semaphore 。 |
|
Semaphore(int permits,
boolean fair)
創建具有給定的許可數和給定的公平設置的 Semaphore 。 |
方法摘要 | |
---|---|
void |
acquire()
從此信號量獲取一個許可,在提供一個許可前一直將執行緒阻塞,否則執行緒被中斷。 |
void |
acquire(int permits)
從此信號量獲取給定數目的許可,在提供這些許可前一直將執行緒阻塞,或者執行緒已被中斷。 |
void |
acquireUninterruptibly()
從此信號量中獲取許可,在有可用的許可前將其阻塞。 |
void |
acquireUninterruptibly(int permits)
從此信號量獲取給定數目的許可,在提供這些許可前一直將執行緒阻塞。 |
int |
availablePermits()
返回此信號量中當前可用的許可數。 |
int |
drainPermits()
獲取並返回立即可用的所有許可。 |
protected Collection<Thread> |
getQueuedThreads()
返回一個 collection,包含可能等待獲取的執行緒。 |
int |
getQueueLength()
返回正在等待獲取的執行緒的估計數目。 |
boolean |
hasQueuedThreads()
查詢是否有執行緒正在等待獲取。 |
boolean |
isFair()
如果此信號量的公平設置為 true,則返回 true 。 |
protected void |
reducePermits(int reduction)
根據指定的縮減量減小可用許可的數目。 |
void |
release()
釋放一個許可,將其返回給信號量。 |
void |
release(int permits)
釋放給定數目的許可,將其返回到信號量。 |
String |
toString()
返回標識此信號量的字元串,以及信號量的狀態。 |
boolean |
tryAcquire()
僅在調用時此信號量存在一個可用許可,才從信號量獲取許可。 |
boolean |
tryAcquire(int permits)
僅在調用時此信號量中有給定數目的許可時,才從此信號量中獲取這些許可。 |
boolean |
tryAcquire(int permits,
long timeout,
TimeUnit unit)
如果在給定的等待時間內此信號量有可用的所有許可,並且當前執行緒未被中斷,則從此信號量獲取給定數目的許可。 |
boolean |
tryAcquire(long timeout,
TimeUnit unit)
如果在給定的等待時間內,此信號量有可用的許可並且當前執行緒未被中斷,則從此信號量獲取一個許可。 |
從類別 java.lang.Object 繼承的方法 |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
建構子詳細資訊 |
---|
public Semaphore(int permits)
Semaphore
。
permits
- 初始的可用許可數目。此值可能為負數,在這種情況下,必須在授予任何獲取前進行釋放。public Semaphore(int permits, boolean fair)
Semaphore
。
permits
- 初始的可用許可數目。此值可能為負數,在這種情況下,必須在授予任何獲取前進行釋放。fair
- 如果此信號量保證在爭用時按先進先出的順序授予許可,則為 true
;否則為 false
。方法詳細資訊 |
---|
public void acquire() throws InterruptedException
獲取一個許可(如果提供了一個)並立即返回,將可用的許可數減 1。
如果沒有可用的許可,則在發生以下兩種情況之一前,禁止將當前執行緒用於執行緒安排目的並使其處於休眠狀態:
如果當前執行緒:
中斷
。
InterruptedException
,並且清除當前執行緒的已中斷狀態。
InterruptedException
- 如果當前執行緒被中斷public void acquireUninterruptibly()
獲取一個許可(如果提供了一個)並立即返回,將可用的允許數減 1。
如果沒有可用的許可,則在其他某些執行緒調用此信號量的 release()
方法,並且當前執行緒是下一個要被分派許可的執行緒前,禁止當前執行緒用於執行緒安排目的並使其處於休眠狀態。
如果當前執行緒在等待許可時被中斷,那麼它將繼續等待,但是與沒有發生中斷,其將接收允許的時間相比,為該執行緒分派許可的時間可能改變。當執行緒確實從此方法返回後,將設置其中斷狀態。
public boolean tryAcquire()
獲取一個許可(如果提供了一個)並立即返回,其值為 true
,將可用的許可數減 1。
如果沒有可用的許可,則此方法立即返回並且值為 false
。
即使已將此信號量設置為使用公平排序策略,但是調用 tryAcquire()
也將 立即獲取許可(如果有一個可用),而不管當前是否有正在等待的執行緒。在某些情況下,此“闖入”行為可能很有用,即使它會打破公平性也如此。如果希望遵守公平設置,則使用 tryAcquire(0, TimeUnit.SECONDS)
,它幾乎是等效的(它也檢測中斷)。
true
;否則返回 false
。public boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException
獲取一個許可(如果提供了一個)並立即返回,其值為 true
,將可用的許可數減 1。
如果沒有可用的允許,則在發生以下三種情況之一前,禁止將當前執行緒用於執行緒安排目的並使其處於休眠狀態:
如果獲取了許可,則返回值為 true
。
如果當前執行緒:
InterruptedException
,並且清除當前執行緒的已中斷狀態。
如果超出了指定的等待時間,則返回值為 false
。如果該時間小於等於 0,則方法根本不等待。
timeout
- 等待許可的最多時間unit
- timeout
參數的時間單位
true
;如果獲取許可前超出了等待時間,則返回 false
InterruptedException
- 如果當前執行緒是已中斷的public void release()
釋放一個許可,將可用的許可數增加 1。如果任意執行緒試圖獲取許可,則選中一個執行緒並將剛剛釋放的許可給予它。然後針對執行緒安排目的啟用(或再啟用)該執行緒。
不要求釋放許可的執行緒必須通過調用 acquire()
來獲取許可。通過應用程序中的程式約定來建立信號量的正確用法。
public void acquire(int permits) throws InterruptedException
獲取給定數目的許可(如果提供了)並立即返回,將可用的許可數減去給定的量。
如果沒有足夠的可用許可,則在發生以下兩種情況之一前,禁止將當前執行緒用於執行緒安排目的並使其處於休眠狀態:
如果當前執行緒:
InterruptedException
,並且清除當前執行緒的已中斷狀態。任何原本應該分派給此執行緒的許可將被分派給其他試圖獲取許可的執行緒,就好像已通過調用 release()
而使許可可用一樣。
permits
- 要獲取的許可數
InterruptedException
- 如果當前執行緒已被中斷
IllegalArgumentException
- 如果 permits
為負public void acquireUninterruptibly(int permits)
獲取給定數目的許可(如果提供了)並立即返回,將可用的許可數減去給定的量。
如果沒有足夠的可用許可,則在其他某些執行緒調用此信號量的某個釋放
方法,當前執行緒是下一個要被分派許可的執行緒,並且可用的許可數目滿足此請求前,禁止當前執行緒用於執行緒安排目的並使其處於休眠狀態。
如果當前的執行緒在等待許可時被中斷,則它會繼續等待並且它在佇列中的位置不受影響。當執行緒確實從此方法返回後,將其設置為中斷狀態。
permits
- 要獲取的許可數
IllegalArgumentException
- 如果 permits
為負public boolean tryAcquire(int permits)
獲取給定數目的許可(如果提供了)並立即返回,其值為 true
,將可用的許可數減去給定的量。
如果沒有足夠的可用許可,則此方法立即返回,其值為 false
,並且不改變可用的許可數。
即使已將此信號量設置為使用公平排序策略,但是調用 tryAcquire
也將 立即獲取許可(如果有一個可用),而不管當前是否有正在等待的執行緒。在某些情況下,此“闖入”行為可能很有用,即使它會打破公平性也如此。如果希望遵守公平設置,則使用 tryAcquire(permits, 0, TimeUnit.SECONDS)
,它幾乎是等效的(它也檢測中斷)。
permits
- 要獲取的許可數
true
;否則返回 false
IllegalArgumentException
- 如果 permits
為負public boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
獲取給定數目的許可(如果提供了)並立即返回,其值為 true
,將可用的許可數減去給定的量。
如果沒有足夠的可用許可,則在發生以下三種情況之一前,禁止將當前執行緒用於執行緒安排目的並使其處於休眠狀態:
如果獲取了許可,則返回值為 true
。
如果當前執行緒:
InterruptedException
,並且清除當前執行緒的已中斷狀態。任何原本應該分派給此執行緒的許可將被分派給其他試圖獲取許可的執行緒,就好像已通過調用 release()
而使許可可用一樣。
如果超出了指定的等待時間,則返回值為 false
。如果該時間小於等於 0,則方法根本不等待。任何原本應該分派給此執行緒的許可將被分派給其他試圖獲取許可的執行緒,就好像已通過調用 release()
而使許可可用一樣。
permits
- 要獲取的許可數timeout
- 等待許可的最多時間unit
- timeout
參數的時間單位
true
;如果獲取所有許可前超出了等待時間,則返回 false
InterruptedException
- 如果當前執行緒是已中斷的
IllegalArgumentException
- 如果 permits
為負public void release(int permits)
釋放給定數目的許可,將可用的許可數增加該量。如果任意執行緒試圖獲取許可,則選中某個執行緒並將剛剛釋放的許可給予該執行緒。如果可用許可的數目滿足該執行緒的請求,則針對執行緒安排目的啟用(或再啟用)該執行緒;否則在有足夠的可用許可前執行緒將一直等待。如果滿足此執行緒的請求後仍有可用的許可,則依次將這些許可分派給試圖獲取許可的其他執行緒。
不要求釋放許可的執行緒必須通過調用獲取
來獲取該許可。通過應用程序中的程式約定來建立信號量的正確用法。
permits
- 要釋放的許可數
IllegalArgumentException
- 如果 permits
為負public int availablePermits()
此方法通常用於除錯和測試目的。
public int drainPermits()
protected void reducePermits(int reduction)
acquire
,在許可變為可用的過程中,它不會阻塞等待。
reduction
- 要移除的許可數
IllegalArgumentException
- 如果 reduction
是負數public boolean isFair()
true
。
true
public final boolean hasQueuedThreads()
true
並不保證有其他執行緒等待獲取許可。此方法主要用於監視系統狀態。
true
public final int getQueueLength()
protected Collection<Thread> getQueuedThreads()
public String toString()
"Permits ="
,後跟許可數。
Object
中的 toString
|
JavaTM 2 Platform Standard Ed. 6 |
|||||||||
上一個類別 下一個類別 | 框架 無框架 | |||||||||
摘要: 巢狀 | 欄位 | 建構子 | 方法 | 詳細資訊: 欄位 | 建構子 | 方法 |
版權所有 2008 Sun Microsystems, Inc. 保留所有權利。請遵守GNU General Public License, version 2 only。