作用
Semaphore(信號量)是用來控制同時訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源。
簡介
Semaphore也是一個線程同步的輔助類,可以維護當前訪問自身的線程個數,並提供了同步機制。使用Semaphore可以控制同時訪問資源的線程個數,例如,實現一個文件允許的並發訪問數。
主要方法摘要:
void acquire():從此信號量獲取一個許可,在提供一個許可前翼子將線程阻塞,否則線程被中斷。
void release():釋放一個許可,將其返回給信號量。
int availablePermits():返回此信號量中當前可用的許可數。
boolean hasQueuedThreads():查詢是否有線程正在等待獲取。
應用場景
Semaphore可以用於做流量控制,特別公用資源有限的應用場景,比如數據庫連接。假如有一個需求,要讀取幾萬個文件的數據,因為都是IO密集型任務,我們可以啟動幾十個線程並發的讀取,但是如果讀到內存后,還需要存儲到數據庫中,而數據庫的連接數只有10個,這時我們必須控制只有十個線程同時獲取數據庫連接保存數據,否則會報錯無法獲取數據庫連接。這個時候,我們就可以使用Semaphore來做流控,代碼如下:
1 public class SemaphoreTest { 2 3 private static final int THREAD_COUNT = 30; 4 5 private static ExecutorService threadPool = Executors 6 .newFixedThreadPool(THREAD_COUNT); 7 8 private static Semaphore s = new Semaphore(10); 9 10 public static void main(String[] args) { 11 for (int i = 0; i < THREAD_COUNT; i++) { 12 threadPool.execute(new Runnable() { 13 @Override 14 public void run() { 15 try { 16 s.acquire(); 17 System.out.println("save data"); 18 s.release(); 19 } catch (InterruptedException e) { 20 } 21 } 22 }); 23 } 24 25 threadPool.shutdown(); 26 } 27 }
在代碼中,雖然有30個線程在執行,但是只允許10個並發的執行。Semaphore的構造方法Semaphore(int permits) 接受一個整型的數字,表示可用的許可證數量。Semaphore(10)表示允許10個線程獲取許可證,也就是最大並發數是10。Semaphore的用法也很簡單,首先線程使用Semaphore的acquire()獲取一個許可證,使用完之后調用release()歸還許可證。還可以用tryAcquire()方法嘗試獲取許可證。
其他方法
Semaphore還提供一些其他方法:
- int availablePermits() :返回此信號量中當前可用的許可證數。
- int getQueueLength():返回正在等待獲取許可證的線程數。
- boolean hasQueuedThreads() :是否有線程正在等待獲取許可證。
- void reducePermits(int reduction) :減少reduction個許可證。是個protected方法。
- Collection getQueuedThreads() :返回所有等待獲取許可證的線程集合。是個protected方法。
參考:《Java並發編程的藝術》