閱讀544 返回首頁    go 阿裏雲 go 技術社區[雲棲]


並發工具類(三)控製並發線程數的Semaphore

簡介

Semaphore(信號量)是用來控製同時訪問特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源。很多年以來,我都覺得從字麵上很難理解Semaphore所表達的含義,隻能把它比作是控製流量的紅綠燈,比如XX馬路要限製流量,隻允許同時有一百輛車在這條路上行使,其他的都必須在路口等待,所以前一百輛車會看到綠燈,可以開進這條馬路,後麵的車會看到紅燈,不能駛入XX馬路,但是如果前一百輛中有五輛車已經離開了XX馬路,那麼後麵就允許有5輛車駛入馬路,這個例子裏說的車就是線程,駛入馬路就表示線程在執行,離開馬路就表示線程執行完成,看見紅燈就表示線程被阻塞,不能執行。

應用場景

Semaphore可以用於做流量控製,特別公用資源有限的應用場景,比如數據庫連接。假如有一個需求,要讀取幾萬個文件的數據,因為都是IO密集型任務,我們可以啟動幾十個線程並發的讀取,但是如果讀到內存後,還需要存儲到數據庫中,而數據庫的連接數隻有10個,這時我們必須控製隻有十個線程同時獲取數據庫連接保存數據,否則會報錯無法獲取數據庫連接。這個時候,我們就可以使用Semaphore來做流控,代碼如下:

public class SemaphoreTest {

	private static final int THREAD_COUNT = 30;

	private static ExecutorService threadPool = Executors
			.newFixedThreadPool(THREAD_COUNT);

	private static Semaphore s = new Semaphore(10);

	public static void main(String[] args) {
		for (int i = 0; i < THREAD_COUNT; i++) {
			threadPool.execute(new Runnable() {
				@Override
				public void run() {
					try {
						s.acquire();
						System.out.println("save data");
						s.release();
					} catch (InterruptedException e) {
					}
				}
			});
		}

		threadPool.shutdown();
	}
}

在代碼中,雖然有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方法。
  • 轉載自 並發編程網 - ifeve.com

最後更新:2017-05-23 17:02:42

  上一篇:go  想用R和Python做文本挖掘又不知如何下手?方法來了!
  下一篇:go  《迷人的8051單片機》---- 1.2小元器件有大智慧