1. 程式人生 > >Java Semaphore用法

Java Semaphore用法

作業系統的訊號量是個很重要的概念,在程序控制方面都有應用。Java 併發庫 的Semaphore 可以很輕鬆完成訊號量控制,Semaphore可以控制某個資源可被同時訪問的個數,acquire()獲取一個許可,如果沒有就等待,而release()釋放一個許可。比如在Windows下可以設定共享檔案的最大客戶端訪問個數。 
Semaphore維護了當前訪問的個數,提供同步機制,控制同時訪問的個數。在資料結構中連結串列可以儲存“無限”的節點,用Semaphore可以實現有限大小的連結串列。另外重入鎖ReentrantLock也可以實現該功能,但實現上要負責些,程式碼也要複雜些。 

下面是模擬一個連線池,控制同一時間最多隻能有50個執行緒訪問。

import java.util.UUID;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class TestSemaphore extends Thread {
	public static void main(String[] args) {
		int i = 0;
		while (i < 500) {
			i++;
			new TestSemaphore().start();
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 控制某資源同時被訪問的個數的類 控制同一時間最後只能有50個訪問
	 */
	static Semaphore semaphore = new Semaphore(50);
	static int timeout = 500;

	public void run() {
		try {
			Object connec = getConnection();
			System.out.println("獲得一個連線" + connec);
			Thread.sleep(300);
			releaseConnection(connec);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void releaseConnection(Object connec) {
		/* 釋放許可 */
		semaphore.release();
		System.out.println("釋放一個連線" + connec);
	}

	public Object getConnection() {
		try {/* 獲取許可 */
			boolean getAccquire = semaphore.tryAcquire(timeout, TimeUnit.MILLISECONDS);
			if (getAccquire) {
				return UUID.randomUUID().toString();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		throw new IllegalArgumentException("timeout");
	}
}