《小緹娜的奇幻之地》PC和主機解鎖時間公開
Semaphore https://www.cnblogs.com/caoleicoding/p/15015067.html
示例程式碼
Semaphore
也是jdk1.5
引入的元件,它的字面意思是訊號量,但是單從字面翻譯我們是無法得知它的作用的,根據官方註釋以及網上的一些解釋,semaphore
簡單來說就是多執行緒執行控制器,它的主要作用就是控制統一時間併發的執行緒數量,從這一特性上看,它最適用的場景就是限流,下面我們通過一段簡單的程式碼來說明它的用法:
public class Example { | |
private static final int THREAD_SIZE = 30; |
|
private static final Semaphore s = new Semaphore(5); | |
public static void main(String[] args) { | |
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_SIZE); | |
for (int i = 0; i < THREAD_SIZE*2; i++) { | |
int finalI = i; | |
executorService.execute(() -> { | |
try { | |
s.acquire(); | |
System.out.println(Thread.currentThread().getName() + " currentTimeMillis: "+ System.currentTimeMillis()); | |
Thread.sleep(2000); | |
System.out.println("thread count: " + finalI); | |
s.release(); | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
}); | |
} | |
executorService.shutdown(); | |
} | |
} |
簡單說明
在上面的程式碼中,我們定義了一個執行緒池,執行緒池大小為30
,同時我們還定義了一個執行緒執行控制器,控制器的大小我們設定為5
,也就是說,在當前控制器的作用下,同一時間只允許5
個執行緒執行;
線上程內部,線上程執行最開始,我們通過Semaphore
的acquire
方法獲取執行許可(拿不到執行憑證是無法執行的),你也可以通過tryAcquire
方法獲取執行憑證,兩個方法的區別是tryAcquire
有一個布林的返回值,是非阻塞的,而acquire
是阻塞的,如果拿不到會一直等,關於這一點,官方文件說的很清楚:
執行緒內部我們休眠了兩秒,然後通過release
方法釋放Semaphore
資源,這樣其他的執行緒才能拿到這個憑證。
最後,我們用一個for
迴圈來執行執行緒,迴圈次數我們設定為執行緒池大小的兩倍,然後我們執行上面的程式碼,執行結果大致如下:
從執行結果中我們可以看到,雖然執行緒池大小是30
,但是同一時間執行的執行緒只有5
個,也就是我們Semaphore
的初始化大小。我們可以試著把Semaphore
的大小修改下看下執行結果:
初始化大小為10
同一時間有10
個執行緒在執行
初始化大小為2
同一時間有2
個執行緒在執行。
作用範圍
下面我們把程式碼做一些簡單調整:
我們分別在acquire
方法前和release
方法後加一行程式碼,這時候我們的semaphore
初始化還是2
,然後執行下:
我們發現,雖然acquire
方法前和release
方法之間以及之後的程式碼雖然同一時間只有兩個執行緒在執行,但是之前的程式碼同一時間是有多於兩個執行緒在執行的,這就是說Semaphore
只會影響acquire
方法前和release
方法之間和之後區域的執行緒併發數,影響之後的程式碼是因為acquire
方法是阻塞的,如果我們換成tryAcquire
應該就是另外一番場景了:
然後執行:
根據執行結果我們發現,這時候acquire
方法前和release
方法之間以及之後的程式碼都不受限制了,都出現了併發數超過限制數的情況。具體原因,我們前面說了,tryAcquire
方法是非阻塞的,所以這時候我們需要人為根據tryAcquire
來控制程式碼邏輯,比如直接結束或者進行其他操作:
boolean b = s.tryAcquire(); | |
if (!b) { | |
// doSomething() | |
System.out.println("未拿到訪問許可權"); | |
return; | |
} |
總結
如果說我們之前講的鎖,是單執行緒鎖(同一時間只執行一個執行緒訪問),那麼Semaphore
更像是一個多執行緒鎖(同一時間允許多個指定執行緒訪問),它也很像我們之前說的令牌桶(限流解決方案),憑令牌資料訪問相關服務,與之不同的是,這裡的Semaphore
可以重複使用的,所以它同樣可以用於限流,比如獲取資料庫連線,我們可以通過Semaphore
來限制連線數。