Java併發程式設計札記-(四)JUC鎖-10Semaphore簡介
阿新 • • 發佈:2019-01-08
一般的鎖在任意時刻只允許一個執行緒訪問一項資源,而計數訊號量允許n個任務同時訪問一項資源。我們可以將訊號量看做一個許可集,可以向執行緒分發使用資源的許可證。獲得資源前,執行緒呼叫acquire()從許可集中獲取許可。該執行緒結束後,通過release()將許可還給許可集。
函式列表
//構造方法摘要
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)
//如果在給定的等待時間內,此訊號量有可用的許可並且當前執行緒未被中斷,則從此訊號量獲取一個許可。
此類的構造方法可選地接受一個公平引數fair。當fair設定為false時,此類不對執行緒獲取許可的順序做任何保證,也就是說可以在已經等待的執行緒前為呼叫acquire() 的執行緒分配一個許可。當公平設定為true時,訊號量保證對於任何呼叫acquire()的執行緒而言,都按照FIFO的規則來選擇執行緒、獲得許可。注意,FIFO排序必然應用到這些方法內的指定內部執行點。所以,可能某個執行緒先於另一個執行緒呼叫了 acquire(),但是卻在該執行緒之後到達排序點,並且從方法返回時也類似。還要注意,非同步的tryAcquire()方法不使用公平設定,而是使用任意可用的許可。
通常,應該將用於控制資源訪問的訊號量初始化為公平的,以確保所有執行緒都可訪問資源。為其他的種類的同步控制使用訊號量時,非公平排序的吞吐量優勢通常要比公平考慮更為重要。
例1:訊號量的簡單使用
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
// 建立許可數為3和非公平的公平設定的 Semaphore。
final Semaphore semp = new Semaphore(3);
// 模擬10個客戶端訪問
for (int index = 0; index < 10; index++) {
Runnable run = new Runnable() {
public void run() {
try {
// 從此訊號量獲取一個許可
semp.acquire();
System.out.println(Thread.currentThread().getName());
} catch (InterruptedException e) {
} finally {
// 釋放訊號量。如果沒有這條語句,則在控制檯只能列印5條記錄,之後執行緒一直阻塞
semp.release();
}
}
};
exec.execute(run);
}
exec.shutdown();
}
}
原始碼
待補充
本文就講到這裡,想了解Java併發程式設計更多內容請參考: