Semaphore的使用和操作系統中的信號量的使用差不多,可以類比去理解。
Semaphore用於限制可以訪問某些資源(物理或邏輯的)的線程數目,他維護了一個許可證集合,有多少資源需要限制就維護多少許可證集合,假如這裏有N個資源,那就對應於N個許可證,同一時刻也只能有N個線程訪問。一個線程獲取許可證就調用acquire方法,用完了釋放資源就調用release方法。
停車場案例代碼實現:
public class CarDemo {
public static void main(String[] args) {
//創建Semaphore
Semaphore sp=new Semaphore(5);
Thread[] car=new Thread[10];
for (int i = 0; i < 10; i++) {
car[i]=new Thread(()->{
//請求許可
try {
sp.acquire();
System.out.println(Thread.currentThread().getName()+"可以進停車場");
} catch (InterruptedException e) {
e.printStackTrace();
}
//使用資源
try {
int val= new Random().nextInt(10);
TimeUnit.SECONDS.sleep(val);
System.out.println(Thread.currentThread().getName()+"停留了"+val+"秒");
} catch (InterruptedException e) {
e.printStackTrace();
}
//離開(釋放資源)
try {
sp.release();
System.out.println(Thread.currentThread().getName()+"離開停車場");
} catch (Exception e) {
e.printStackTrace();
}
},"car["+i+"]");
car[i].start();
}
}
}
其他方法:
在上面我們使用最基本的acquire方法和release方法就可以實現Semaphore最常見的功能,不過其他方法還是需要我們去了解一下的。
1、acquire(int permits)
從此信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞,或者線程已被中斷。就好比是一個學生佔兩個窗口。這同時也對應了相應的release方法。
2、release(int permits)
釋放給定數目的許可,將其返回到信號量。這個是對應於上面的方法,一個學生佔幾個窗口完事之後還要釋放多少
3、availablePermits()
返回此信號量中當前可用的許可數。也就是返回當前還有多少個窗口可用。
4、reducePermits(int reduction)
根據指定的縮減量減小可用許可的數目。
5、hasQueuedThreads()
查詢是否有線程正在等待獲取資源。
6、getQueueLength()
返回正在等待獲取的線程的估計數目。該值僅是估計的數字。
7、tryAcquire(int permits, long timeout, TimeUnit unit)
如果在給定的等待時間內此信號量有可用的所有許可,並且當前線程未被中斷,則從此信號量獲取給定數目的許可。
8、acquireUninterruptibly(int permits)
從此信號量獲取給定數目的許可,在提供這些許可前一直將線程阻塞。