Semaphore的簡介及應用場景
阿新 • • 發佈:2019-02-14
Semaphore是一個計數訊號量,常用於限制可以訪問某些資源(物理或邏輯的)執行緒數目。
常用函式:
訊號量的建構函式
非公平:
public Semaphore(int permits);//permits就是允許同時執行的執行緒數目
公平(獲得鎖的順序與執行緒啟動順序有關):
public Semaphore(int permits,boolean fair);//permits就是允許同時執行的執行緒數目
建立一個訊號量
Semaphore semaphore = new Semaphore(2);
從訊號量中獲取一個許可
semaphore.acquire ();
釋放一個許可(在釋放許可之前,必須先獲獲得許可。)
semaphore.release();
嘗試獲取一個許可,若獲取成功返回true,若獲取失敗返回false
semaphore.tryAcquire();
所有函式:
// 建立具有給定的許可數和非公平的公平設定的 Semaphore。
Semaphore(int permits)
// 建立具有給定的許可數和給定的公平設定的 Semaphore。
Semaphore(int permits, boolean fair)
// 從此訊號量獲取一個許可,在提供一個許可前一直將執行緒阻塞,否則執行緒被中斷。
void acquire()
// 從此訊號量獲取給定數目的許可,在提供這些許可前一直將執行緒阻塞,或者執行緒已被中斷。
void acquire(int permits)
// 從此訊號量中獲取許可,在有可用的許可前將其阻塞。
void acquireUninterruptibly()
// 從此訊號量獲取給定數目的許可,在提供這些許可前一直將執行緒阻塞。
void acquireUninterruptibly(int permits)
// 返回此訊號量中當前可用的許可數。
int availablePermits()
// 獲取並返回立即可用的所有許可。
int drainPermits()
// 返回一個 collection,包含可能等待獲取的執行緒。
protected Collection<Thread> getQueuedThreads ()
// 返回正在等待獲取的執行緒的估計數目。
int getQueueLength()
// 查詢是否有執行緒正在等待獲取。
boolean hasQueuedThreads()
// 如果此訊號量的公平設定為 true,則返回 true。
boolean isFair()
// 根據指定的縮減量減小可用許可的數目。
protected void reducePermits(int reduction)
// 釋放一個許可,將其返回給訊號量。
void release()
// 釋放給定數目的許可,將其返回到訊號量。
void release(int permits)
// 返回標識此訊號量的字串,以及訊號量的狀態。
String toString()
// 僅在呼叫時此訊號量存在一個可用許可,才從訊號量獲取許可。
boolean tryAcquire()
// 僅在呼叫時此訊號量中有給定數目的許可時,才從此訊號量中獲取這些許可。
boolean tryAcquire(int permits)
// 如果在給定的等待時間內此訊號量有可用的所有許可,並且當前執行緒未被中斷,則從此訊號量獲取給定數目的許可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit)
// 如果在給定的等待時間內,此訊號量有可用的許可並且當前執行緒未被中斷,則從此訊號量獲取一個許可。
boolean tryAcquire(long timeout, TimeUnit unit)
程式碼例項:
假設有10個人在銀行辦理業務,只有2個工作視窗,程式碼實現邏輯如下
package com..concurrency.yuxin.demo;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
@Slf4j
public class SemaphoreDemo {
// 排隊總人數(請求總數)
public static int clientTotal = 10;
// 可同時受理業務的視窗數量(同時併發執行的執行緒數)
public static int threadTotal = 2;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal; i++) {
final int count = i;
executorService.execute(() -> {
try {
semaphore.acquire(1);
resolve(count);
semaphore.release(2);
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
}
private static void resolve(int i) throws InterruptedException {
log.info("服務號{},受理業務中。。。", i);
Thread.sleep(2000);
}
}
輸出結果:
21:39:10.038 [pool-1-thread-1] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號0,受理業務中。。。
21:39:10.038 [pool-1-thread-2] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號1,受理業務中。。。
21:39:12.043 [pool-1-thread-4] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號3,受理業務中。。。
21:39:12.043 [pool-1-thread-3] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號2,受理業務中。。。
21:39:14.044 [pool-1-thread-6] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號5,受理業務中。。。
21:39:14.044 [pool-1-thread-5] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號4,受理業務中。。。
21:39:16.045 [pool-1-thread-7] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號6,受理業務中。。。
21:39:16.045 [pool-1-thread-8] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號7,受理業務中。。。
21:39:18.045 [pool-1-thread-10] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號9,受理業務中。。。
21:39:18.045 [pool-1-thread-9] INFO com.concurrency.yuxin.demo.SemaphoreDemo - 服務號8,受理業務中。。。
從輸出結果可以看出,每隔兩秒,有兩個執行緒被執行