天天看點

一、Java多線程并發同步之Semaphore

概念

Semaphore是一種在多線程環境下使用的設施,該設施負責協調各個線程,用來

管理資源

,以保證它們能夠正确、合理的使用公共資源的設施,也是作業系統中用于控制程序同步互斥的量。用我們常見的說法就是用來

控制并發

數。

信号量是一個非負整數 。

業務場景

以售票視窗買票為例,假設火車站有兩個售票視窗,一開始兩個視窗都是沒有人的,這是同時來了10個人買票,每次隻允許2個人同時買票,每個視窗前一個人買完後面的人接着買,而其他人就排隊等待前面的人買完離開,如此往複。

上述場景中10個人就是10個線程,2個視窗就是資源,信号量就是控制2個視窗,

當開始售票時,有2個人能擷取允許進入視窗買票,其信号量就會減2,剩下的人就進入等待狀态,當其中一個人完成買票,就會釋放一個視窗,信号量就會加1,馬上會有另外一個人擷取允許進入視窗,信号量就減1,如此一次循環下去,直到所有人買完票,釋放所有視窗。

實作

Semaphore(int permits):構造方法,建立具有給定許可數的計數信号量并設定為非公平信号量。

Semaphore(int permits,boolean fair):構造方法,當fair等于true時,建立具有給定許可數的計數信号量并設定為公平信号量(FIFO)。

void acquire():擷取資源

void acquire():釋放資源

public class SemaphoreTest {
	/**
	 * 執行任務 操作信号量
	 *
	 */
	class BuyRunnable implements Runnable {
		private Semaphore semaphore;
		private int user;
		
		public BuyRunnable(Semaphore semaphore,int user){
			this.semaphore = semaphore;
			this.user = user;
		}

		@Override
		public void run() {
			try {
				semaphore.acquire(); // 擷取資訊量許可(可以買票)
				System.out.println("user" + user + "---進入視窗,準備開始買票");
				// 模拟買票,每個人使用視窗買票的時間不定
				Thread.sleep((long)(Math.random()*10000));
				System.out.println("user" + user + "---買票完成,準備離開視窗");
				Thread.sleep((long)(Math.random()*10000));
				System.out.println("user" + user + "---離開視窗");
				
				semaphore.release(); // 釋放許可(視窗空了)
				System.out.println("目前可使用的許可數為:"+semaphore.availablePermits());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	public static void main(String[] args) {
		SemaphoreTest semaphoreTest = new SemaphoreTest();
		ExecutorService pool = Executors.newCachedThreadPool();
		final Semaphore semaohore = new Semaphore(2); // 定義兩個視窗
		
		//10個使用者買票
		for (int i = 0; i < 10; i++) {
			pool.execute(semaphoreTest.new BuyRunnable(semaohore,(i+1)));
		}
		pool.shutdown();
	}
}
           

輸出結果:

user1---進入視窗,準備開始買票
user4---進入視窗,準備開始買票
user4---買票完成,準備離開視窗
user1---買票完成,準備離開視窗
user1---離開視窗
目前可使用的許可數為:1
user5---進入視窗,準備開始買票
user4---離開視窗
user8---進入視窗,準備開始買票
目前可使用的許可數為:0
user5---買票完成,準備離開視窗
user5---離開視窗
user9---進入視窗,準備開始買票
目前可使用的許可數為:0
user8---買票完成,準備離開視窗
user9---買票完成,準備離開視窗
user9---離開視窗
user2---進入視窗,準備開始買票
目前可使用的許可數為:0
user8---離開視窗
目前可使用的許可數為:1
user3---進入視窗,準備開始買票
user2---買票完成,準備離開視窗
user3---買票完成,準備離開視窗
user2---離開視窗
user6---進入視窗,準備開始買票
目前可使用的許可數為:0
user3---離開視窗
user7---進入視窗,準備開始買票
目前可使用的許可數為:0
user6---買票完成,準備離開視窗
user7---買票完成,準備離開視窗
user6---離開視窗
目前可使用的許可數為:1
user10---進入視窗,準備開始買票
user7---離開視窗
目前可使用的許可數為:1
user10---買票完成,準備離開視窗
user10---離開視窗
目前可使用的許可數為:2

           

結論

使用Semaphore資訊量主要就是控制線程并發數,諸如上述業務場景其實還有很多,例如停車場車位,排隊上廁所等等,都可以通過Semaphore來控制。

繼續閱讀