天天看點

Java并發工具類---控制并發線程數的Semaphore

 Semaphore(信号量)用來控制同時通路特定資源的線程數量,它通過協調各個線程,以保證合理的使用公共資源。

 其實,Semaphore就好比交通燈,用于控制車流,車子就好比線程。

應用場景

 Semaphore可以用于做流量控制,特别是公用資源有限的應用場景,比如資料庫連接配接。假如有一個需求,要讀取幾萬個檔案的資料,因為都是IO密集型任務,我們可以啟動幾十個線程并發地讀取,但是如果讀到記憶體後,還需要存儲到資料庫中,而資料庫的連接配接數隻有10個,這時我們必須控制隻有10個線程同時擷取資料庫連接配接儲存資料,否則會報錯無法擷取資料庫連接配接。這個時候,就可以使用Semaphore來做流量控制。

SemaphoreTest.java

public class SemaphoreTest { 
	private static final int THREAD_COUNT = 30; 
	private static ExecutorServicethreadPool = Executors.newFixedThreadPool(THREAD_COUNT); 
	private static Semaphore s = new Semaphore(10); 
	public static void main(String[] args) { 
		for (inti = 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還提供一些其他方法,具體如下。 ·

  • intavailablePermits():傳回此信号量中目前可用的許可證數。
  • intgetQueueLength():傳回正在等待擷取許可證的線程數。
  • booleanhasQueuedThreads():是否有線程正在等待擷取許可證。
  • void reducePermits(int reduction):減少reduction個許可證,是個protected方法。
  • Collection getQueuedThreads():傳回所有等待擷取許可證的線程集合,是個protected方法。