一、概念
Semaphore是一個計數信號量,常用於限制可以訪問某些資源(物理或邏輯的)線程數目。
一個信號量有且僅有3種操作,且它們全部是原子的:初始化、增加和減少
增加可以為一個進程解除阻塞;
減少可以讓一個進程進入阻塞。
和線程池的區別:使用Seamphore,創建了多少線程,實際就會有多少線程進行執行,只是可同時執行的線程數量會受到限制。但使用線程池,不管你創建多少線程,實際可執行的線程數是一定的。
二、方法
1 構造方法:
Semaphore(int)、Semaphore(int,boolean)
int表示該信號量擁有的許可數量
boolean表示獲取許可的時候是否是公平的。(公平指的是先來的先執行)
2 獲取許可
acquire()、acquire(int)、tryAcquire()
int參數表示一次性要獲取幾個許可,默認為1個,acquire方法在沒有許可的情況下,要獲取許可的線程會阻塞。
tryAcquire()方法在沒有許可的情況下會立即返回 false,要獲取許可的線程不會阻塞。
3 釋放許可
release()、release(int)
int參數表示一次性要釋放幾個許可,默認為1個,
注意一個線程調用release()之前並不要求一定要調用了acquire因此如果釋放的比獲取的信號量還多,例如獲取了2個,釋放了5次,那么當前信號量就動態的增加為5了(實現動態增加)
4 當前可用的許可數
int availablePermits()
三、測試
public
void
testSemaphore()
{
// 線程池
ExecutorService exec = Executors.newCachedThreadPool();
// 只能5個線程同時訪問
final
Semaphore semp =
new
Semaphore(
2
);
// 模擬20個客戶端訪問
for
(
int
index =
0
; index <
5
; index++) {
final
int
NO = index;
Runnable run =
new
Runnable() {
@Override
public
void
run() {
try
{
if
(semp.availablePermits() >
0
) {
System.out.println( NO +
"線程啟動"
);
}
else
{
System.out.println(NO +
"線程啟動,排隊等待"
);
}
// 獲取許可
semp.acquire();
System.out.println(NO +
"線程執行"
);
//模擬實際業務邏輯
Thread.sleep((
long
) (Math.random() *
10000
));
// 訪問完后,釋放
semp.release();
System.out.println(NO +
"線程釋放"
);
}
catch
(InterruptedException e) {
}
}
};
exec.execute(run);
}
try
{
Thread.sleep(
10
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
//System.out.println(semp.getQueueLength());
// 退出線程池
exec.shutdown();
}
|
0線程啟動
0線程執行
1線程啟動
1線程執行
2線程啟動,排隊等待
3線程啟動,排隊等待
4線程啟動,排隊等待
2線程執行
0線程釋放
1線程釋放
3線程執行
2線程釋放
4線程執行
3線程釋放
4線程釋放