摘要:多線程工具箱之前言這一篇談一下信號量。信息信息信息信息信息信息信息信息信息信息信息小結(jié)適用于多線程請求數(shù)量資源的場景,但無法解決單多個線程對同一資源訪問的競爭性訪問。在后面我們在我們的多線程工具箱里面陸續(xù)會提到。
Java多線程工具箱之Semaphore 前言
這一篇談一下Semaphore:信號量。
將Semaphore類比為為信號燈,被繼承Runable的線程類比為列車:理解信號量可以參考控制列車的信號燈:鐵道上有多個列車,由信號燈通知其可用情況。若列車拿到的信號燈為綠燈,列車可以通過,否則列車不能通過。
Semaphore用于限制訪問線程多于可用資源的場景。
1.1 基本API 構(gòu)造器 Semaphore(int premits)構(gòu)造傳入初始化的允許數(shù)量。
方法 acquire()請求允許,未有有效的允許或者中斷之前,線程將會阻塞。
方法 release()釋放允許。
1.2 范例在范例中,我們使用一個機場請求跑道的模擬程序,機場有3個跑道,這個時段降落的航班一共有10個。由于跑道遠沒有飛機的數(shù)量多,因此需要飛機需要等待可用的跑道資源。這個程序就是模擬了這個過程。
UML App.javaimport java.util.Random; import lombok.extern.java.Log; @Log public class App { static Random ran = new Random(System.currentTimeMillis()); public static void main(String[] args) { Airport ap = new Airport("Baiyun Airport", 3); for (int index = 0; index < 10; index++) { AirPlane plane = new AirPlane(index, String.valueOf(index), String.valueOf(index), ap, ran.nextInt(2) == 0 ? Action.landing : Action.takeOff); Thread thread = new Thread(plane); thread.start(); } } }
import java.util.Arrays; import java.util.concurrent.Semaphore; import lombok.Data; import lombok.extern.java.Log; @Log @Data public class Airport { private String name; private Semaphore semaphore; private Runway[] runways; public Airport(String name, int numberOfRunway) { this.name = name; this.semaphore = new Semaphore(numberOfRunway); runways = new Runway[numberOfRunway]; for (int index = 0; index < numberOfRunway; index++) { Runway currentRunway = new Runway(name, index); runways[index] = currentRunway; } log.info("Airpot is ready :" + Arrays.toString(runways)); } public Runway requestRunway() throws InterruptedException { semaphore.acquire(); while (true) { for (int index = 0; index < runways.length; index++) { Runway runway = runways[index]; if (!runway.isInUse()) { runway.setInUse(true); return runway; } } log.warning("all runway is using, and wait till there is runay release."); } } public void releaseRunway(Runway release) { for (int index = 0; index < runways.length; index++) { Runway runway = runways[index]; if (runway.equals(release)) { runway.setInUse(false); semaphore.release(); } } } }Airplane.java
import java.util.Random; import lombok.Data; import lombok.extern.java.Log; @Data @Log public class AirPlane implements Runnable { private int id; private String name; private String company; private Airport airport; private Action action; private static Random rand = new Random(System.currentTimeMillis()); public AirPlane(int id, String name, String company, Airport airport, Action action) { this.id = id; this.name = name; this.company = company; this.airport = airport; this.action = action; } @Override public void run() { Runway runway = null; try { runway = airport.requestRunway(); log.info(this.toString() + "is using " + runway.toString() + " to " + this.action); int sleepSecond = rand.nextInt(10) * 1000; Thread.sleep(sleepSecond); } catch (InterruptedException e) { log.warning("request runway error"); e.printStackTrace(); } finally { if (airport != null && runway != null) { airport.releaseRunway(runway); } } } }Runway.java
import lombok.Data; @Data public class Runway { private String name; private boolean inUse = false; public Runway(String airportName, int runwayIndex) { this.name = airportName + "_" + runwayIndex; } }運行結(jié)果
可以從運行結(jié)果中看到,程序運行的第一秒,首先幾架的飛機(線程)都第一時間的獲得了跑道(資源),而后面幾架飛機(線程),則在前面的飛機退出(sleep)跑道(資源)后獲得使用權(quán),進行起飛或降落。
Aug 13, 2018 12:56:32 AM online.tangbk.thread.study.semaphore.Airport1.3 Semaphore小結(jié)信息: Airpot is ready :[Runway(name=Baiyun Airport_0, inUse=false), Runway(name=Baiyun Airport_1, inUse=false), Runway(name=Baiyun Airport_2, inUse=false)] Aug 13, 2018 12:56:33 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=1, name=1, company=1, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 1], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=false)]), action=landing)is using Runway(name=Baiyun Airport_1, inUse=true) to landing Aug 13, 2018 12:56:33 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=2, name=2, company=2, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=takeOff)is using Runway(name=Baiyun Airport_2, inUse=true) to takeOff Aug 13, 2018 12:56:33 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=0, name=0, company=0, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 2], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=false), Runway(name=Baiyun Airport_2, inUse=false)]), action=landing)is using Runway(name=Baiyun Airport_0, inUse=true) to landing Aug 13, 2018 12:56:33 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=8, name=8, company=8, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=takeOff)is using Runway(name=Baiyun Airport_1, inUse=true) to takeOff Aug 13, 2018 12:56:35 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=3, name=3, company=3, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=takeOff)is using Runway(name=Baiyun Airport_0, inUse=true) to takeOff Aug 13, 2018 12:56:37 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=4, name=4, company=4, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=landing)is using Runway(name=Baiyun Airport_2, inUse=true) to landing Aug 13, 2018 12:56:40 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=5, name=5, company=5, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=landing)is using Runway(name=Baiyun Airport_2, inUse=true) to landing Aug 13, 2018 12:56:40 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=6, name=6, company=6, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=landing)is using Runway(name=Baiyun Airport_2, inUse=true) to landing Aug 13, 2018 12:56:41 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=7, name=7, company=7, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=takeOff)is using Runway(name=Baiyun Airport_1, inUse=true) to takeOff Aug 13, 2018 12:56:41 AM online.tangbk.thread.study.semaphore.AirPlane run 信息: AirPlane(id=9, name=9, company=9, airport=Airport(name=Baiyun Airport, semaphore=java.util.concurrent.Semaphore@61a09c6b[Permits = 0], runways=[Runway(name=Baiyun Airport_0, inUse=true), Runway(name=Baiyun Airport_1, inUse=true), Runway(name=Baiyun Airport_2, inUse=true)]), action=landing)is using Runway(name=Baiyun Airport_0, inUse=true) to landing
Semaphore適用于多線程請求數(shù)量資源的場景,但無法解決單多個線程對同一資源訪問的競爭性訪問。對于單一資源的競爭性訪問,依然要使用synchronize關(guān)鍵字或atomic等甚至ReadWriteLock關(guān)鍵字或工具類進行限制。
在后面我們在我們的多線程工具箱里面陸續(xù)會提到。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76733.html
摘要:當線程使用完共享資源后,可以歸還許可,以供其它需要的線程使用。所以,并不會阻塞調(diào)用線程。立即減少指定數(shù)目的可用許可數(shù)。方法用于將可用許可數(shù)清零,并返回清零前的許可數(shù)六的類接口聲明類聲明構(gòu)造器接口聲明 showImg(https://segmentfault.com/img/bVbfdnC?w=1920&h=1200); 本文首發(fā)于一世流云的專欄:https://segmentfault...
摘要:整個包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執(zhí)行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據(jù)一系列常見的多線程設計模式,設計了并發(fā)包,其中包下提供了一系列基礎的鎖工具,用以對等進行補充增強。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發(fā)于一世流云專欄:https...
摘要:在每個線程獲取之前,必須先從信號量獲取許可。注意,因為同時可能發(fā)生取消,所以返回并不保證有其他線程等待獲取許可。該值僅是估計的數(shù)字,因為在此方法遍歷內(nèi)部數(shù)據(jù)結(jié)構(gòu)的同時,線程的數(shù)目可能動態(tài)地變化。 本人郵箱: 歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明網(wǎng)址 http://blog.csdn.net/tianshi_kcogithub: https://github.com/kco1989/kco代碼已經(jīng)全部托...
摘要:前言之前學多線程的時候沒有學習線程的同步工具類輔助類。而其它線程完成自己的操作后,調(diào)用使計數(shù)器減。信號量控制一組線程同時執(zhí)行。 前言 之前學多線程的時候沒有學習線程的同步工具類(輔助類)。ps:當時覺得暫時用不上,認為是挺高深的知識點就沒去管了.. 在前幾天,朋友發(fā)了一篇比較好的Semaphore文章過來,然后在瀏覽博客的時候又發(fā)現(xiàn)面試還會考,那還是挺重要的知識點。于是花了點時間去了解...
摘要:初始時,為,當調(diào)用方法時,線程的加,當調(diào)用方法時,如果為,則調(diào)用線程進入阻塞狀態(tài)。該對象一般供監(jiān)視診斷工具確定線程受阻塞的原因時使用。 showImg(https://segmentfault.com/img/remote/1460000016012503); 本文首發(fā)于一世流云的專欄:https://segmentfault.com/blog... 一、LockSupport類簡介...
閱讀 1049·2021-11-24 09:39
閱讀 3578·2021-11-22 13:54
閱讀 2542·2021-10-11 10:59
閱讀 773·2021-09-02 15:40
閱讀 1025·2019-08-30 15:55
閱讀 1042·2019-08-30 13:57
閱讀 2305·2019-08-30 13:17
閱讀 3025·2019-08-29 18:32