成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

詳解Java 信號量Semaphore

瀏覽:4日期:2022-08-24 17:41:31

Semaphore也是一個同步器,和前面兩篇說的CountDownLatch和CyclicBarrier不同,這是遞增的,初始化的時候可以指定一個值,但是不需要知道需要同步的線程個數,只需要在同步的地方調用acquire方法時指定需要同步的線程個數;

一.簡單使用

同步兩個子線程,只有其中兩個子線程執行完畢,主線程才會執行:

package com.example.demo.study;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class Study0217 { //創建一個信號量的實例,信號量初始值為0 static Semaphore semaphore = new Semaphore(0); public static void main(String[] args) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(3); pool.submit(()->{ System.out.println('Thread1---start'); //信號量加一 semaphore.release(); });pool.submit(()->{ System.out.println('Thread2---start'); //信號量加一 semaphore.release(); }); pool.submit(()->{ System.out.println('Thread3---start'); //信號量加一 semaphore.release(); }); //等待兩個子線程執行完畢就放過,必須要信號量等于2才放過 semaphore.acquire(2); System.out.println('兩個子線程執行完畢');//關閉線程池,正在執行的任務繼續執行 pool.shutdown(); }}

詳解Java 信號量Semaphore

這個信號量也可以復用,類似CyclicBarrier:

package com.example.demo.study;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class Study0217 { //創建一個信號量的實例,信號量初始值為0 static Semaphore semaphore = new Semaphore(0); public static void main(String[] args) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(3); pool.submit(()->{ System.out.println('Thread1---start'); //信號量加一 semaphore.release(); });pool.submit(()->{ System.out.println('Thread2---start'); //信號量加一 semaphore.release(); });//等待兩個子線程執行完畢就放過,必須要信號量等于2才放過 semaphore.acquire(2); System.out.println('子線程1,2執行完畢');pool.submit(()->{ System.out.println('Thread3---start'); //信號量加一 semaphore.release(); }); pool.submit(()->{ System.out.println('Thread4---start'); //信號量加一 semaphore.release(); });semaphore.acquire(2); System.out.println('子線程3,4執行完畢');//關閉線程池,正在執行的任務繼續執行 pool.shutdown(); }}

詳解Java 信號量Semaphore

二.信號量原理 

看看下面這個圖,可以知道信號量Semaphore還是根據AQS實現的,內部有個Sync工具類操作AQS,還分為公平策略和非公平策略;

詳解Java 信號量Semaphore

構造器:

//默認是非公平策略public Semaphore(int permits) { sync = new NonfairSync(permits);}//可以根據第二個參數選擇是公平策略還是非公平策略public Semaphore(int permits, boolean fair) { sync = fair ? new FairSync(permits) : new NonfairSync(permits);}

acquire(int permits)方法:

public void acquire(int permits) throws InterruptedException { if (permits < 0) throw new IllegalArgumentException(); sync.acquireSharedInterruptibly(permits);}//AQS中的方法public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); //這里根據子類是公平策略還是非公平策略 if (tryAcquireShared(arg) < 0) //獲取失敗會進入這里,將線程放入阻塞隊列,然后再嘗試,還是失敗的話就調用park方法掛起當前線程 doAcquireSharedInterruptibly(arg);}//非公平策略protected int tryAcquireShared(int acquires) { return nonfairTryAcquireShared(acquires);}final int nonfairTryAcquireShared(int acquires) { //一個無限循環,獲取state剩余的信號量,因為每調用一次release()方法的話,信號量就會加一,這里將 //最新的信號量減去傳進來的參數比較,比如有兩個線程,其中一個線程已經調用了release方法,然后調用acquire(2)方法,那么 //這里remaining的值就是-1,返回-1,然后當前線程就會被丟到阻塞隊列中去了;如果另外一個線程也調用了release方法, //那么此時的remaining==0,所以在這里的if中會調用CAS將0設置到state // for (;;) { int available = getState(); int remaining = available - acquires; if (remaining < 0 || compareAndSetState(available, remaining)) return remaining; }}//公平策略//和上面非公平差不多,只不過這里會查看阻塞隊列中當前節點前面有沒有前驅節點,有的話直接返回-1,//就會把當前線程丟到阻塞隊列中阻塞去了,沒有前驅節點的話,就跟非公平模式一樣的了protected int tryAcquireShared(int acquires) { for (;;) { if (hasQueuedPredecessors()) return -1; int available = getState(); int remaining = available - acquires; if (remaining < 0 ||compareAndSetState(available, remaining)) return remaining; }}

再看看release(int permits)方法:

//這個方法的作用就是將信號量加一public void release(int permits) { if (permits < 0) throw new IllegalArgumentException(); sync.releaseShared(permits);}//AQS中方法public final boolean releaseShared(int arg) { //tryReleaseShared嘗試釋放資源 if (tryReleaseShared(arg)) { //釋放資源成功就調用park方法喚醒喚醒AQS隊列中最前面的節點中的線程 doReleaseShared(); return true; } return false;}protected final boolean tryReleaseShared(int releases) { //一個無限循環,獲取state,然后加上傳進去的參數,如果新的state的值小于舊的state,說明已經超過了state的最大值,溢出了 //沒有溢出的話,就用CAS更新state的值 for (;;) { int current = getState(); int next = current + releases; if (next < current) // overflow throw new Error('Maximum permit count exceeded'); if (compareAndSetState(current, next)) return true; }}private void doReleaseShared() { for (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; //ws==Node.SIGNAL表示節點中線程需要被喚醒 if (ws == Node.SIGNAL) {if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases//調用阻塞隊列中線程的unpark方法喚醒線程unparkSuccessor(h); } //ws == 0表示節點中線程是初始狀態 else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))continue;// loop on failed CAS }if (h == head) // loop if head changed break; }}

以最上面的例子簡單說一下,其實不是很難,首先線程1和線程2分別去調用release方法,這個方法里面會將AQS中的state加一,但是在執行這個操作之前,主線程肯定會先到acquire(2),在這個方法里面,假如默認使用非公平策略,首先獲取當前的信號量state(state的初始值是0),用當前信號量減去2,如果小于0,那么當前主線程就會丟到AQS隊列中阻塞;

這個時候線程1的release方法執行了,于是就把信號量state加一(此時state==1),CAS更新state為一,成功的話,就調用doReleaseShared()方法喚醒AQS阻塞隊列中最先掛起的線程(這里就是因為調用acquire方法而阻塞的主線程),主線程喚醒之后又會去獲取最新的信號量,與2比較,發現還是小于0,于是又會阻塞;

線程2此時的release方法執行完成,重復線程一的操作,主線程喚醒之后(此時state==2),又去獲取最新的信號量發現是2,減去acquire方法的參數2等于0,于是就用CAS更新state的值,然后acquire方法也就執行完畢,主線程繼續執行后面的代碼;

其實信號量還是很有意思的,記得在項目里,有人利用信號量實現了一個故障隔離,什么時候我可以把整理之后的代碼貼出來分享一下,還是很有意思的,就跟springcloud的熔斷機制差不多,場景是:比如你在service的一個方法調用第三方的接口,你不知道調不調得通,而且你不希望每次前端過來都會去調用,比如當調用失敗的次數超過100次,那么五分鐘之后才會再去實際調用這個第三方服務!這五分鐘內前調用這個服務,就會觸發我們這個故障隔離的機制,向前端返回一個特定的錯誤碼和錯誤信息!

以上就是詳解Java 信號量Semaphore的詳細內容,更多關于Java 信號量Semaphore的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
中文字幕高清一区| 色久综合一二码| 欧美吻胸吃奶大尺度电影 | 欧美精品一区男女天堂| 国产精品亚洲第一区在线暖暖韩国| 91成人国产精品| 奇米在线7777在线精品| 一区视频在线| 欧美mv和日韩mv国产网站| 成人免费看视频| 精品福利二区三区| 91麻豆蜜桃一区二区三区| 国产欧美日韩卡一| 伊人久久亚洲美女图片| 亚洲免费av在线| 国产麻豆综合| 丝袜美腿亚洲综合| 欧美三级欧美一级| 国产成人午夜电影网| 精品久久久久久亚洲综合网| 91在线国内视频| 中文在线免费一区三区高中清不卡| 国产精品观看| 一区二区三区蜜桃网| 久久久久国内| 黄色成人免费在线| 精品国产a毛片| 国产一区二区无遮挡| 亚洲日本va午夜在线电影| 国产精品亚洲不卡a| 日韩va亚洲va欧美va久久| 欧美日韩精品一区二区三区| 福利电影一区二区三区| 国产亚洲一区二区三区四区| 禁久久精品乱码| 五月天视频一区| 欧美精品在线观看一区二区| 丁香激情综合国产| 中文字幕va一区二区三区| 99亚洲视频| 日韩成人av影视| 欧美精品一卡两卡| 99精品久久99久久久久| 亚洲欧美另类图片小说| 色综合久久久久综合体桃花网| 国产美女视频一区| 国产日韩欧美综合一区| 国产一区二区三区成人欧美日韩在线观看| 日韩高清不卡一区二区三区| 91精品国产乱| 欧美xxx在线观看| 亚洲精品高清在线| 在线观看一区日韩| av在线不卡电影| 亚洲精品乱码久久久久久| 在线免费观看视频一区| 成av人片一区二区| 一区二区三区在线观看动漫| 欧美三级中文字幕在线观看| 99久久夜色精品国产网站| 一区二区三区四区精品在线视频| 日本韩国一区二区三区视频| 成人一区在线观看| 日韩一区在线看| 欧美在线观看一区| 欧美日韩日本网| 免费日本视频一区| 久久久久久一二三区| 亚洲一区二区三区在线观看视频 | 在线日韩中文| 国产在线观看免费一区| 国产精品私人影院| 欧美午夜精品一区| 国产精品啊啊啊| 九一九一国产精品| 国产精品久久久久久久第一福利| 在线视频欧美精品| 欧美日韩在线一二三| 美女视频黄a大片欧美| 国产日韩三级在线| 欧美三级电影网| 红桃视频国产精品| 狠狠色丁香婷婷综合久久片| 一色屋精品亚洲香蕉网站| 在线中文字幕一区二区| 91丨porny丨蝌蚪视频| 亚洲激情在线| 成人小视频在线观看| 国产香蕉久久精品综合网| 色婷婷av一区二区| 欧美精品亚洲精品| 国产亚洲一区二区三区在线观看| 久久成人免费| 午夜国产精品视频免费体验区| 男女激情视频一区| 国产精品护士白丝一区av| 欧美特级限制片免费在线观看| 在线观看成人av电影| 国产成人av影院| 亚洲午夜成aⅴ人片| 久久久av毛片精品| 欧美色大人视频| 宅男噜噜噜66一区二区 | 久久影院亚洲| 欧美午夜在线视频| 国产高清在线观看免费不卡| 亚洲高清免费在线| 亚洲国产精品成人综合| 777午夜精品免费视频| 欧美专区在线| 99久久精品国产一区二区三区 | 麻豆成人在线| 欧美体内she精视频在线观看| 久国产精品韩国三级视频| 亚洲黄色片在线观看| 精品对白一区国产伦| 欧美午夜精品一区| 久久精品导航| 精品国产制服丝袜高跟| 欧美日韩在线三级| 免费亚洲电影| 亚洲高清在线播放| 欧美ab在线视频| 成人91在线观看| 韩国女主播一区| 日韩精品免费视频人成| 一区二区三区毛片| 国产精品家庭影院| 国产欧美一区二区三区网站| 日韩三级视频中文字幕| 在线观看亚洲精品视频| 亚洲激情网址| 好看的日韩av电影| 91视频在线看| 成人性生交大合| 国产在线播放一区三区四| 555夜色666亚洲国产免| 在线观看欧美日本| 国产三区二区一区久久| 国内精品美女在线观看| 女女同性女同一区二区三区91| 亚洲国产aⅴ天堂久久| 伊人婷婷欧美激情| 亚洲欧美日韩国产一区二区三区 | 国产精品一二三四| 美女诱惑一区二区| 日本成人在线一区| 午夜视频久久久久久| 亚洲午夜在线观看视频在线| 亚洲男同性视频| 国产精品免费观看视频| 欧美激情自拍偷拍| 日本一区二区免费在线| 久久精品人人做人人爽人人| 26uuu久久综合| 欧美精品一区二区高清在线观看| 日韩欧美亚洲一区二区| 欧美日韩亚洲国产综合| 欧美艳星brazzers| 欧美日韩亚洲综合在线| 欧美日本不卡视频| 欧美日韩第一区日日骚| 欧美日韩在线综合| 欧美日韩精品电影| 欧美美女一区二区在线观看| 欧美日韩另类国产亚洲欧美一级| 在线观看精品一区| 一本色道精品久久一区二区三区| 136国产福利精品导航网址| 亚洲视频狠狠| 亚洲国产一区二区三区在线播| 国产精品成人观看视频免费| 国语自产精品视频在线看抢先版结局 | 亚洲一区二区三区精品在线| 亚洲综合色网站| 亚洲图片欧美综合| 日韩国产在线一| 久久99精品视频| 丰满白嫩尤物一区二区| 成人av免费在线| 欧美在线三级| 韩国自拍一区| 亚洲一区二区三区色| 色婷婷av久久久久久久| 日本电影欧美片| 欧美日本一区二区三区| 欧美性受xxxx| 欧美老年两性高潮| 日韩欧美一级精品久久| 26uuu另类欧美| 国产精品麻豆99久久久久久| 中文字幕亚洲电影| 亚洲福利电影网| 日本美女视频一区二区| 久久99国内精品| 精品国产一区二区在线观看| 国产亚洲女人久久久久毛片| 国产精品久久久久久久久果冻传媒 | 国产精品综合二区| 成人免费毛片片v|