小編給大家分享一下java并發(fā)工具類之Semaphore,Exchanger的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)專注于襄州企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計(jì),購(gòu)物商城網(wǎng)站建設(shè)。襄州網(wǎng)站建設(shè)公司,為襄州等地區(qū)提供建站服務(wù)。全流程按需搭建網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
1. 控制資源并發(fā)訪問--Semaphore
Semaphore可以理解為信號(hào)量,用于控制資源能夠被并發(fā)訪問的線程數(shù)量,以保證多個(gè)線程能夠合理的使用特定資源。
Semaphore就相當(dāng)于一個(gè)許可證,線程需要先通過acquire方法獲取該許可證,該線程才能繼續(xù)往下執(zhí)行,否則只能在該方法出阻塞等待。當(dāng)執(zhí)行完業(yè)務(wù)功能后,需要通過release()方法將許可證歸還,以便其他線程能夠獲得許可證繼續(xù)執(zhí)行。
Semaphore可以用于做流量控制,特別是公共資源有限的應(yīng)用場(chǎng)景,比如數(shù)據(jù)庫(kù)連接。假如有多個(gè)線程讀取數(shù)據(jù)后,需要將數(shù)據(jù)保存在數(shù)據(jù)庫(kù)中,而可用的最大數(shù)據(jù)庫(kù)連接只有10個(gè),這時(shí)候就需要使用Semaphore來控制能夠并發(fā)訪問到數(shù)據(jù)庫(kù)連接資源的線程個(gè)數(shù)最多只有10個(gè)。在限制資源使用的應(yīng)用場(chǎng)景下,Semaphore是特別合適的。
下面來看下Semaphore的主要方法:
//獲取許可,如果無法獲取到,則阻塞等待直至能夠獲取為止 void acquire() throws InterruptedException //同acquire方法功能基本一樣,只不過該方法可以一次獲取多個(gè)許可 void acquire(int permits) throws InterruptedException //釋放許可 void release() //釋放指定個(gè)數(shù)的許可 void release(int permits) //嘗試獲取許可,如果能夠獲取成功則立即返回true,否則,則返回false boolean tryAcquire() //與tryAcquire方法一致,只不過這里可以指定獲取多個(gè)許可 boolean tryAcquire(int permits) //嘗試獲取許可,如果能夠立即獲取到或者在指定時(shí)間內(nèi)能夠獲取到,則返回true,否則返回false boolean tryAcquire(long timeout, TimeUnit unit) throws InterruptedException //與上一個(gè)方法一致,只不過這里能夠獲取多個(gè)許可 boolean tryAcquire(int permits, long timeout, TimeUnit unit) //返回當(dāng)前可用的許可證個(gè)數(shù) int availablePermits() //返回正在等待獲取許可證的線程數(shù) int getQueueLength() //是否有線程正在等待獲取許可證 boolean hasQueuedThreads() //獲取所有正在等待許可的線程集合 Collection<Thread> getQueuedThreads()
另外,在Semaphore的構(gòu)造方法中還支持指定是夠具有公平性,默認(rèn)的是非公平性,這樣也是為了保證吞吐量。
一個(gè)例子
下面用一個(gè)簡(jiǎn)單的例子來說明Semaphore的具體使用。我們來模擬這樣一樣場(chǎng)景。有一天,班主任需要班上10個(gè)同學(xué)到講臺(tái)上來填寫一個(gè)表格,但是老師只準(zhǔn)備了5支筆,因此,只能保證同時(shí)只有5個(gè)同學(xué)能夠拿到筆并填寫表格,沒有獲取到筆的同學(xué)只能夠等前面的同學(xué)用完之后,才能拿到筆去填寫表格。該示例代碼如下:
public class SemaphoreDemo { //表示老師只有10支筆 private static Semaphore semaphore = new Semaphore(5); public static void main(String[] args) { //表示50個(gè)學(xué)生 ExecutorService service = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { service.execute(() -> { try { System.out.println(Thread.currentThread().getName() + " 同學(xué)準(zhǔn)備獲取筆......"); semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " 同學(xué)獲取到筆"); System.out.println(Thread.currentThread().getName() + " 填寫表格ing....."); TimeUnit.SECONDS.sleep(3); semaphore.release(); System.out.println(Thread.currentThread().getName() + " 填寫完表格,歸還了筆!?。。。?!"); } catch (InterruptedException e) { e.printStackTrace(); } }); } service.shutdown(); } }
輸出結(jié)果:
pool-1-thread-1 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-1 同學(xué)獲取到筆 pool-1-thread-1 填寫表格ing..... pool-1-thread-2 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-2 同學(xué)獲取到筆 pool-1-thread-2 填寫表格ing..... pool-1-thread-3 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-4 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-3 同學(xué)獲取到筆 pool-1-thread-4 同學(xué)獲取到筆 pool-1-thread-4 填寫表格ing..... pool-1-thread-3 填寫表格ing..... pool-1-thread-5 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-5 同學(xué)獲取到筆 pool-1-thread-5 填寫表格ing..... pool-1-thread-6 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-7 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-8 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-9 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-10 同學(xué)準(zhǔn)備獲取筆...... pool-1-thread-4 填寫完表格,歸還了筆?。。。。?! pool-1-thread-9 同學(xué)獲取到筆 pool-1-thread-9 填寫表格ing..... pool-1-thread-5 填寫完表格,歸還了筆?。。。。?! pool-1-thread-7 同學(xué)獲取到筆 pool-1-thread-7 填寫表格ing..... pool-1-thread-8 同學(xué)獲取到筆 pool-1-thread-8 填寫表格ing..... pool-1-thread-1 填寫完表格,歸還了筆?。。。。?! pool-1-thread-6 同學(xué)獲取到筆 pool-1-thread-6 填寫表格ing..... pool-1-thread-3 填寫完表格,歸還了筆?。。。。?! pool-1-thread-2 填寫完表格,歸還了筆?。。。。。? pool-1-thread-10 同學(xué)獲取到筆 pool-1-thread-10 填寫表格ing..... pool-1-thread-7 填寫完表格,歸還了筆!?。。。。? pool-1-thread-9 填寫完表格,歸還了筆!?。。。?! pool-1-thread-8 填寫完表格,歸還了筆!?。。。。? pool-1-thread-6 填寫完表格,歸還了筆!?。。。?! pool-1-thread-10 填寫完表格,歸還了筆?。。。。。?/pre>根據(jù)輸出結(jié)果進(jìn)行分析,Semaphore允許的最大許可數(shù)為5,也就是允許的最大并發(fā)執(zhí)行的線程個(gè)數(shù)為5,可以看出,前5個(gè)線程(前5個(gè)學(xué)生)先獲取到筆,然后填寫表格,而6-10這5個(gè)線程,由于獲取不到許可,只能阻塞等待。
當(dāng)線程pool-1-thread-4釋放了許可之后,pool-1-thread-9就可以獲取到許可,繼續(xù)往下執(zhí)行。對(duì)其他線程的執(zhí)行過程,也是同樣的道理。
從這個(gè)例子就可以看出,Semaphore用來做特殊資源的并發(fā)訪問控制是相當(dāng)合適的,如果有業(yè)務(wù)場(chǎng)景需要進(jìn)行流量控制,可以優(yōu)先考慮Semaphore。
2.線程間交換數(shù)據(jù)的工具--Exchanger
Exchanger是一個(gè)用于線程間協(xié)作的工具類,用于兩個(gè)線程間能夠交換。它提供了一個(gè)交換的同步點(diǎn),在這個(gè)同步點(diǎn)兩個(gè)線程能夠交換數(shù)據(jù)。
具體交換數(shù)據(jù)是通過exchange方法來實(shí)現(xiàn)的,如果一個(gè)線程先執(zhí)行exchange方法,那么它會(huì)同步等待另一個(gè)線程也執(zhí)行exchange方法,這個(gè)時(shí)候兩個(gè)線程就都達(dá)到了同步點(diǎn),兩個(gè)線程就可以交換數(shù)據(jù)。
Exchanger除了一個(gè)無參的構(gòu)造方法外,主要方法也很簡(jiǎn)單:
//當(dāng)一個(gè)線程執(zhí)行該方法的時(shí)候,會(huì)等待另一個(gè)線程也執(zhí)行該方法,因此兩個(gè)線程就都達(dá)到了同步點(diǎn) //將數(shù)據(jù)交換給另一個(gè)線程,同時(shí)返回獲取的數(shù)據(jù) V exchange(V x) throws InterruptedException //同上一個(gè)方法功能基本一樣,只不過這個(gè)方法同步等待的時(shí)候,增加了超時(shí)時(shí)間 V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException一個(gè)例子
Exchanger理解起來很容易,這里用一個(gè)簡(jiǎn)單的例子來看下它的具體使用。我們來模擬這樣一個(gè)情景,在青春洋溢的中學(xué)時(shí)代,下課期間,男生經(jīng)常會(huì)給走廊里為自己喜歡的女孩子送情書,相信大家都做過這樣的事情吧 :)。男孩會(huì)先到女孩教室門口,然后等女孩出來,教室那里就是一個(gè)同步點(diǎn),然后彼此交換信物,也就是彼此交換了數(shù)據(jù)。現(xiàn)在,就來模擬這個(gè)情景。
public class ExchangerDemo { private static Exchanger<String> exchanger = new Exchanger(); public static void main(String[] args) { //代表男生和女生 ExecutorService service = Executors.newFixedThreadPool(2); service.execute(() -> { try { //男生對(duì)女生說的話 String girl = exchanger.exchange("我其實(shí)暗戀你很久了......"); System.out.println("女孩兒說:" + girl); } catch (InterruptedException e) { e.printStackTrace(); } }); service.execute(() -> { try { System.out.println("女生慢慢的從教室你走出來......"); TimeUnit.SECONDS.sleep(3); //男生對(duì)女生說的話 String boy = exchanger.exchange("我也很喜歡你......"); System.out.println("男孩兒說:" + boy); } catch (InterruptedException e) { e.printStackTrace(); } }); } }輸出結(jié)果:
女生慢慢的從教室你走出來...... 男孩兒說:我其實(shí)暗戀你很久了...... 女孩兒說:我也很喜歡你......這個(gè)例子很簡(jiǎn)單,也很能說明Exchanger的基本使用。當(dāng)兩個(gè)線程都到達(dá)調(diào)用exchange方法的同步點(diǎn)的時(shí)候,兩個(gè)線程就能交換彼此的數(shù)據(jù)。
以上是“java并發(fā)工具類之Semaphore,Exchanger的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
網(wǎng)頁(yè)名稱:java并發(fā)工具類之Semaphore,Exchanger的示例分析
分享網(wǎng)址:http://jinyejixie.com/article6/gpgcig.html成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計(jì)、網(wǎng)站策劃、網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站設(shè)計(jì)公司、外貿(mào)建站、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)