Semaphore [ˈseməfɔːr] 可以維護當前訪問自身的線程個數,並提供了同步機制。使用Semaphore可以控制同時訪問資源的線程個數(即允許n個任務同時訪問這個資源),例如,實現一個文件允許的並發訪問數。
Semaphore實現的功能就類似廁所有5個坑,假如有十個人要上廁所,那么同時能有多少個人去上廁所呢?同時只能有5個人能夠占用,當5個人中的任何一個人讓開后,其中在等待的另外5個人中又有一個可以占用了。
另外等待的5個人中可以是隨機獲得優先機會,也可以是按照先來后到的順序獲得機會,這取決於構造Semaphore對象時傳入的參數選項。
單個信號量的Semaphore對象可以實現互斥鎖的功能,並且可以是由一個線程獲得了“鎖”,再由另一個線程釋放“鎖”,這可應用於死鎖恢復的一些場合。
通過acquire()和release()獲取和釋放訪問許可,Semaphore可以初始化是0,然后通過release來變成1
sp.availablePermits()可以獲取當前可訪問的許可的數量
sp.drainPermits()可以把所有許可全部清零
package java_thread; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class SemaphoreTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Semaphore sp = new Semaphore(3); for(int i=0;i<10;i++){ Runnable runnable = new Runnable(){ public void run(){ try { sp.acquire(); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println("線程" + Thread.currentThread().getName() + "進入,當前已有" + (3-sp.availablePermits()) + "個並發"); try { Thread.sleep((long)(Math.random()*10000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("線程" + Thread.currentThread().getName() + "即將離開"); sp.release(); //下面代碼有時候執行不准確,因為其沒有和上面的代碼合成原子單元 System.out.println("線程" + Thread.currentThread().getName() + "已離開,當前已有" + (3-sp.availablePermits()) + "個並發"); } }; service.execute(runnable); } } }