Java中Semaphore信號(hào)量的方法解析
一、簡(jiǎn)介
Semaphore(信號(hào)量)是用來(lái)控制同 時(shí)訪問(wèn) 特定 資 源的 線(xiàn) 程數(shù)量,它通 過(guò)協(xié)調(diào) 各個(gè) 線(xiàn) 程,以 保 證 合理的使用公共 資源。實(shí)現(xiàn)其實(shí)就是一個(gè)共享鎖,是基于AQS實(shí)現(xiàn)的,通過(guò)state變量來(lái)實(shí)現(xiàn)共享。通過(guò)調(diào)用acquire方法,對(duì)state值減去一,當(dāng)調(diào)用release的時(shí)候,對(duì)state值加一。當(dāng)state變量小于0的時(shí)候,在AQS隊(duì)列中阻塞等待
二、使用場(chǎng)景
當(dāng)我們需要對(duì)某個(gè)任務(wù)限制資源使用時(shí),比如我們這個(gè)系統(tǒng) 有多個(gè)接口,其中一個(gè)接口不重要其他接口特別重要,這時(shí)候就可以通過(guò)信號(hào)量限制這個(gè)接口可使用的線(xiàn)程數(shù)量防止再一些特殊情況這個(gè)接口使用超量的線(xiàn)程資源從而影響到重要任務(wù)的執(zhí)行
三、構(gòu)造方法
Semaphore可以實(shí)現(xiàn)公平和非公平
public Semaphore(int permits) { sync = new NonfairSync(permits); } public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits); }
其中NonfairSync和FairSync都是繼承自Sync,而Sync繼承于AQS所以Semaphore就是通過(guò)AQS實(shí)現(xiàn)的
abstract static class Sync extends AbstractQueuedSynchronizer { Sync(int permits) { setState(permits); } }
從這里可以看出來(lái)調(diào)用了AQS的setState方法,讀過(guò)前面的文章應(yīng)該明白AQS的核心就是內(nèi)部維護(hù)著一個(gè)volatile修飾的同步狀態(tài)值state。所以說(shuō)當(dāng)我們new Semaphore(10)時(shí)候,實(shí)際上是在AQS的框架中初始化了一個(gè)同步狀態(tài)為10的值。
四、acquire方法
public void acquire() throws InterruptedException { sync.acquireSharedInterruptibly(1); } public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) doAcquireSharedInterruptibly(arg); }
protected int tryAcquireShared(int acquires) { return nonfairTryAcquireShared(acquires); } final int nonfairTryAcquireShared(int acquires) { for (;;) { int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; } }
通過(guò)源代碼我們發(fā)現(xiàn)此處semphore處理獲取鎖的業(yè)務(wù)邏輯是:
- 獲取同步狀態(tài)值
- 每個(gè)線(xiàn)程進(jìn)來(lái)就減去請(qǐng)求的值,此處請(qǐng)求的值是1.然后用可用同步狀態(tài)值減去請(qǐng)求的值得到同步狀態(tài)剩余的值。
- 如果請(qǐng)求的值大于可用的值或者CAS操作把可用值改為剩余可用的值那么就返回剩下可用的值。
五、release()釋放鎖
Semaphore semaphore=new Semaphore(10); semaphore.release(); public void release() { sync.releaseShared(1); }
此處sync調(diào)用了AQS中的方法releaseShared,在這個(gè)方法中如果釋放成功那么就調(diào)用doReleaseShared方法,此方法在前面AQS共享模式文章中已經(jīng)講解過(guò),此處不在詳細(xì)講解。它主要作用就是釋放隊(duì)列中的節(jié)點(diǎn)。
六、整體流程
附上網(wǎng)圖
七、實(shí)例代碼
public static void main(String[] args) throws InterruptedException, BrokenBarrierException { Semaphore semaphore = new Semaphore(5); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8, 10, 3, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); for (int i = 0; i < 20; i++) { threadPoolExecutor.execute(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "開(kāi)始執(zhí)行"); Thread.sleep(2000); System.out.println(Thread.currentThread().getName() + "執(zhí)行成功############"); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } }); } }
輸出:
可以看出最多只有五個(gè)線(xiàn)程在執(zhí)行
到此這篇關(guān)于Java中Semaphore信號(hào)量的方法解析的文章就介紹到這了,更多相關(guān)Semaphore信號(hào)量的方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA 2021.1 EAP 4 發(fā)布:字體粗細(xì)可調(diào)整Git commit template 支持
這篇文章主要介紹了IntelliJ IDEA 2021.1 EAP 4 發(fā)布:字體粗細(xì)可調(diào)整,Git commit template 支持,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02intellij idea使用git stash暫存一次提交的操作
這篇文章主要介紹了intellij idea使用git stash暫存一次提交的操作,具有很好的參考價(jià)值希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02解決Properties屬性文件中的值有等號(hào)和換行的小問(wèn)題
這篇文章主要介紹了解決Properties屬性文件中的值有等號(hào)有換行的小問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java基礎(chǔ)之toString的序列化 匿名對(duì)象 復(fù)雜度精解
序列化即為把內(nèi)存中的對(duì)象轉(zhuǎn)換為字節(jié)寫(xiě)入文件或通過(guò)網(wǎng)絡(luò)傳輸?shù)竭h(yuǎn)端服務(wù)器,本章節(jié)將帶你了解Java toString的序列化 匿名對(duì)象 復(fù)雜度,需要的朋友可以參考下2021-09-09詳解spring cloud如何使用spring-test進(jìn)行單元測(cè)試
這篇文章主要介紹了spring cloud如何使用spring-test進(jìn)行單元測(cè)試,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Java數(shù)組擴(kuò)容實(shí)現(xiàn)方法解析
這篇文章主要介紹了Java數(shù)組擴(kuò)容實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11帶你盤(pán)點(diǎn)Java的五種運(yùn)算符
這篇文章主要介紹了Java基本數(shù)據(jù)類(lèi)型和運(yùn)算符,結(jié)合實(shí)例形式詳細(xì)分析了java基本數(shù)據(jù)類(lèi)型、數(shù)據(jù)類(lèi)型轉(zhuǎn)換、算術(shù)運(yùn)算符、邏輯運(yùn)算符等相關(guān)原理與操作技巧,需要的朋友可以參考下2021-07-07Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之工作管理系統(tǒng)的實(shí)現(xiàn)
這是一個(gè)使用了java+SSM+Jsp+Mysql開(kāi)發(fā)的工作干活管理系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有管理系統(tǒng)該有的所有功能,感興趣的朋友快來(lái)看看吧2022-02-02