摘要:演示代碼獲取一個許可釋放一個許可我們在執(zhí)行方式前后包裹上和,這樣其實我們就相當(dāng)于一個單線程在執(zhí)行。嘗試獲取一個許可釋放一個許可這次我們使用的是一個方法,這個方法的第一個參數(shù)是表示等待毫秒,第二參數(shù)是表示多長時間嘗試一次,表示毫秒。
Semaphore
是用于控制某個資源同一時間被線程訪問的個數(shù),提供acquire()和release()方法,acquire獲取一個許可,如果沒有獲取的到就等待,release是在操作完成后釋放一個許可,Semaphore維護(hù)了當(dāng)前訪問的個數(shù),通過同步機制來控制同時訪問的個數(shù),在數(shù)據(jù)結(jié)構(gòu)里鏈表中的節(jié)點是可以無限個的,而Semaphore里維護(hù)的是一個有大小的限鏈表。
Semaphore用于僅能提供有限訪問的資源,比如數(shù)據(jù)庫中的鏈接數(shù)只有20但是我們上層應(yīng)用數(shù)可能遠(yuǎn)大于20,如果同時都對數(shù)據(jù)庫鏈接進(jìn)行獲取,那很定會因為鏈接獲取不到而報錯,所以我們就要對數(shù)據(jù)庫鏈接的訪問進(jìn)行控制。
@Slf4j public class SemaphoreExample1 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { semaphore.acquire(); // 獲取一個許可 test(threadNum); semaphore.release(); // 釋放一個許可 } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
我們在執(zhí)行 test(threadNum)方式前后包裹上acquire和release,這樣其實我們就相當(dāng)于一個單線程在執(zhí)行。當(dāng)執(zhí)行acquire后就只能等待執(zhí)行release后再執(zhí)行新的線程,然后我們在acquire()和release()都是沒有傳參也就是1,每次只允許一個線程執(zhí)行,如果我們改成
semaphore.acquire(3); // 獲取多個許可 test(threadNum); semaphore.release(3); // 釋放多個許可
那么我們就是每3個3個執(zhí)行直到把線程池中的線程執(zhí)行完。在打印的日志中我們也可以看到是每三個每三個打印。
Semaphore提供了一個嘗試獲取許可的方法,tryAcquire()嘗試獲取許可成功就執(zhí)行,嘗試獲取許可失敗就丟棄線程。下面看代碼
@Slf4j public class SemaphoreExample3 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { if (semaphore.tryAcquire()) { // 嘗試獲取一個許可 test(threadNum); semaphore.release(); // 釋放一個許可 } } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
這段代碼執(zhí)行結(jié)果就只打印了3行日志,其他的線程就被丟棄了。tryAcquire()共提供如下幾種方法。
我們用一個例子來演示一下參數(shù)的方法的使用。
@Slf4j public class SemaphoreExample4 { private final static int threadCount = 20; public static void main(String[] args) throws Exception { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { final int threadNum = i; exec.execute(() -> { try { if (semaphore.tryAcquire(5000, TimeUnit.MILLISECONDS)) { // 嘗試獲取一個許可 test(threadNum); semaphore.release(); // 釋放一個許可 } } catch (Exception e) { log.error("exception", e); } }); } exec.shutdown(); } private static void test(int threadNum) throws Exception { log.info("{}", threadNum); Thread.sleep(1000); } }
這次我們使用的是一個tryAcquire(5000, TimeUnit.MILLISECONDS))方法,這個方法的第一個參數(shù)是表示等待5000毫秒,第二參數(shù)是表示多長時間嘗試一次,TimeUnit.MILLISECONDS表示1毫秒。這時候我們會發(fā)現(xiàn)20個線程都執(zhí)行了,為什么會這樣呢?因為我們在執(zhí)行時等待超時時間是5秒,每次執(zhí)行就是sleep 1秒,所以可以獲取成tryAcquire進(jìn)而執(zhí)行。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/77671.html
摘要:性能較好是因為避免了線程進(jìn)入內(nèi)核的阻塞狀態(tài)請求總數(shù)同時并發(fā)執(zhí)行的線程數(shù)我們首先使用聲明一個所得實例,然后使用進(jìn)行加鎖和解鎖操作。 ReentrantLock與鎖 Synchronized和ReentrantLock異同 可重入性:兩者都具有可重入性 鎖的實現(xiàn):Synchronized是依賴jvm實現(xiàn)的,ReentrantLock是jdk實現(xiàn)的。(我們可以理解為一個是操作系統(tǒng)層面的實現(xiàn)...
摘要:當(dāng)線程使用完共享資源后,可以歸還許可,以供其它需要的線程使用。所以,并不會阻塞調(diào)用線程。立即減少指定數(shù)目的可用許可數(shù)。方法用于將可用許可數(shù)清零,并返回清零前的許可數(shù)六的類接口聲明類聲明構(gòu)造器接口聲明 showImg(https://segmentfault.com/img/bVbfdnC?w=1920&h=1200); 本文首發(fā)于一世流云的專欄:https://segmentfault...
摘要:簡介抽象隊列同步器,以下簡稱出現(xiàn)在中,由大師所創(chuàng)作。獲取成功則返回,獲取失敗,線程進(jìn)入同步隊列等待。響應(yīng)中斷版的超時響應(yīng)中斷版的共享式獲取同步狀態(tài),同一時刻可能會有多個線程獲得同步狀態(tài)。 1.簡介 AbstractQueuedSynchronizer (抽象隊列同步器,以下簡稱 AQS)出現(xiàn)在 JDK 1.5 中,由大師 Doug Lea 所創(chuàng)作。AQS 是很多同步器的基礎(chǔ)框架,比如 ...
摘要:簡介抽象隊列同步器,以下簡稱出現(xiàn)在中,由大師所創(chuàng)作。獲取成功則返回,獲取失敗,線程進(jìn)入同步隊列等待。響應(yīng)中斷版的超時響應(yīng)中斷版的共享式獲取同步狀態(tài),同一時刻可能會有多個線程獲得同步狀態(tài)。 1.簡介 AbstractQueuedSynchronizer (抽象隊列同步器,以下簡稱 AQS)出現(xiàn)在 JDK 1.5 中,由大師 Doug Lea 所創(chuàng)作。AQS 是很多同步器的基礎(chǔ)框架,比如 ...
摘要:所有示例代碼請見下載于基本概念并發(fā)同時擁有兩個或者多個線程,如果程序在單核處理器上運行多個線程將交替地?fù)Q入或者換出內(nèi)存這些線程是同時存在的,每個線程都處于執(zhí)行過程中的某個狀態(tài),如果運行在多核處理器上此時,程序中的每個線程都 所有示例代碼,請見/下載于 https://github.com/Wasabi1234... showImg(https://upload-images.jians...
閱讀 3069·2021-09-28 09:43
閱讀 902·2021-09-08 09:35
閱讀 1440·2019-08-30 15:56
閱讀 1183·2019-08-30 13:00
閱讀 2732·2019-08-29 18:35
閱讀 1829·2019-08-29 14:07
閱讀 3432·2019-08-29 13:13
閱讀 1333·2019-08-29 12:40