【java.util.concurrent】Semaphore詳解

概念:java

一個計數信號量,信號量維護了一個許可集。Semaphore 只對可用許可的號碼進行計數,並採起相應的行動。拿到信號量的線程能夠進入代碼,不然就等待。經過acquire()和release()獲取和釋放訪問許可。ide

  • acquire():獲取從這個信號量許可證,阻塞直到有一個可用,或線程被中斷。
  • release() :釋放一個許可,將可用的許可數增長 1。若是任意線程試圖獲取許可,則選中一個線程並將剛剛釋放的許可給予它。

驗證示例:ui

public class SemaphoreTest {
	private static int MAX_VALUE = 5;
	private static List<Integer> list = new LinkedList<Integer>();
	private static Map<Integer, Integer> map = new HashMap<Integer, Integer>();
	
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		/* Semaphore能夠控制某個資源可被同時訪問的個數
		 * 
		 * Semaphore(int permits)
		 * Semaphore(int permits, boolean fair)
		 *
		 * permits 初始許可數,也就是最大訪問線程數
		 * fair 當設置爲false時,線程獲取許可的順序是無序的,也就是說新線程可能會比等待的老線程會先得到許可;
		 * 當設置爲true時,信號量保證它們調用的順序(即先進先出;FIFO)
		 */
		Semaphore semaphore = new Semaphore(MAX_VALUE, true);
		ExecutorService es = Executors.newCachedThreadPool();//Executor接口擁有execute方法,ExecutorService繼承Executor
		for(int i=0; i<4*MAX_VALUE; i++){
			//內部類訪問成員變量,若局部變量不修改的狀況下能夠省去final關鍵字,since1.8;若改變,編譯器將提示局部變量必須爲final類型
			final int index = i;
			es.execute(new PRunnable(semaphore, index));
		}
		Thread.sleep(300);
		//退出線程池
		es.shutdown();
		System.out.println("最後還有"+semaphore.availablePermits()+"個許可可用");
	}
}

class PRunnable implements Runnable{
	private final Semaphore semaphore;
	private int index;
	
	public PRunnable(Semaphore semaphore, int index){
		this.semaphore = semaphore;
		this.index = index;
	}
	
	public void getAcquire(){
		System.out.println(index+"號車進入");
	}
	
	public void releaseAcquire(){
		System.out.println(index+"號車離開");
	}
	
	@Override
	public void run() {
		try {
			//acquire() 獲取從這個信號量許可證,阻塞直到有一個可用,或線程被中斷。
			semaphore.acquire();
			getAcquire();
			//release() 釋放一個許可,將可用的許可數增長 1。若是任意線程試圖獲取許可,則選中一個線程並將剛剛釋放的許可給予它。
			semaphore.release();
			releaseAcquire();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

 若是屏蔽semaphore.release()語句,則在控制檯只能打印 MAX_VALUE 條記錄,以後線程一直阻塞。this

相關文章
相關標籤/搜索