摘要:將屏障重置為其初始狀態(tài)。注意,在由于其他原因造成損壞之后,實(shí)行重置可能會(huì)變得很復(fù)雜此時(shí)需要使用其他方式重新同步線程,并選擇其中一個(gè)線程來執(zhí)行重置。
安全共享對(duì)象策略
1.線程限制 : 一個(gè)被線程限制的對(duì)象,由線程獨(dú)占,并且只能被占有它的線程修改
2.共享只讀 : 一個(gè)共享只讀的對(duì)象,在沒有額外同步的情況下,可以被多個(gè)線程并發(fā)訪問,
但是任何線程都不能修改它
3.線程安全對(duì)象 : 一個(gè)線程安全的對(duì)象或則容器,在內(nèi)部通過同步機(jī)制來保證線程安全,
所以其他線程無需額外的同步就可以通過公共接口隨意訪問它
4.被守護(hù)對(duì)象 : 被守護(hù)對(duì)象只能通過獲取特定的鎖來訪問
采用synchronized關(guān)鍵字同步,缺點(diǎn) :
不能完成做到線程安全
性能差
ArrayLisy -> Vector, Stack
HashMap -> HashTable (key、value不能為null)
Collections.synchronizedXXX(List、Set、Map)
ArrayList -> CopyOnWriteArrayList
HashSet、TreeSet -> CopyOnWriteArraySet ConcurrentSkipListSet
HashMap、TreeMap -> ConcurrentHashMap ConcurrentSkipListMap
AbstractQueuedSynchronizer - AQS
使用Node實(shí)現(xiàn)FIFO隊(duì)列,可以用于構(gòu)建鎖或則其他同步裝置的基礎(chǔ)框架
利用一個(gè)int類型表示狀態(tài)
使用方法是基礎(chǔ)
子類通過繼承并通過實(shí)現(xiàn)它的方法管理其狀態(tài) { acquire 和 release} 的方法操縱狀態(tài)
可以同時(shí)實(shí)現(xiàn)排他鎖和共享鎖模式(獨(dú)占、共享)
常用類CountDownLatch
Semaphore
CyclicBarrier
ReentrantLock
Condition
FutureTask
CountDownLatch是一個(gè)同步工具類,它允許一個(gè)或多個(gè)線程一直等待,直到其他線程執(zhí)行完后再執(zhí)行。例如,應(yīng)用程序的主線程希望在負(fù)責(zé)啟動(dòng)框架服務(wù)的線程已經(jīng)啟動(dòng)所有框架服務(wù)之后執(zhí)行。
CountDownLatch是通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的,計(jì)數(shù)器的初始化值為線程的數(shù)量。每當(dāng)一個(gè)線程完成了自己的任務(wù)后,計(jì)數(shù)器的值就相應(yīng)得減1。當(dāng)計(jì)數(shù)器到達(dá)0時(shí),表示所有的線程都已完成任務(wù),然后在閉鎖上等待的線程就可以恢復(fù)執(zhí)行任務(wù)。
@Self4j public class CountDownLatchExample { private final static int threadCount = 200; public static void main(String[] arg) { ExecutorService exec = Executors.newCachedThreadPool(); final CountDownLatch lacth = new CountDownLatch(5); for (int i = 0; i < 1000; i++) { exec.excute( () -> { final int threadNum = i; try { test(threadNum); } catch (Exception e) { log.error("exception", e); } finally { // latch遞減 lacth.countDown(); } }); } // 等待latch計(jì)數(shù)器為0,則繼續(xù)往下執(zhí)行 latch.await(); // latch的await方法也可以傳入等待時(shí)間,等到等待時(shí)間后不管有沒完成計(jì)數(shù)都往下執(zhí)行 // latch.await( 10, TimeUnit.MILLISECONDS); log.info("finished"); exec.shutdown(); } public static void test(int i) throw Exception{ log.info("thread: {}", i); } }Semaphore
Semaphore(int permits):構(gòu)造方法,創(chuàng)建具有給定許可數(shù)的計(jì)數(shù)信號(hào)量并設(shè)置為非公平信號(hào)量。
Semaphore(int permits,boolean fair):構(gòu)造方法,當(dāng)fair等于true時(shí),創(chuàng)建具有給定許可數(shù)的計(jì)數(shù)信號(hào)量并設(shè)置為公平信號(hào)量。
void acquire():從此信號(hào)量獲取一個(gè)許可前線程將一直阻塞。
void acquire(int n):從此信號(hào)量獲取給定數(shù)目許可,在提供這些許可前一直將線程阻塞。
void release():釋放一個(gè)許可,將其返回給信號(hào)量。就如同車開走返回一個(gè)車位。
void release(int n):釋放n個(gè)許可。
int availablePermits():獲取當(dāng)前可用的許可數(shù)。
boolean tryAcquire():僅在調(diào)用時(shí)此信號(hào)量存在一個(gè)可用許可,才從信號(hào)量獲取許可。
boolean tryAcquire(int permits):僅在調(diào)用時(shí)此信號(hào)量中有給定數(shù)目的許可時(shí),才從此信號(hào)量中獲取這些許可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
如果在給定的等待時(shí)間內(nèi)此信號(hào)量有可用的所有許可,并且當(dāng)前線程未被 中斷,則從此信號(hào)量獲取給定數(shù)目的許可。
@Self4j public class SemaphoreExample { private final static int threadCount = 200; public static void main(String[] arg) { ExecutorService exec = Executors.newCachedThreadPool(); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < threadCount; i++) { exec.excute( () )-> { final int threadNum = i; try { // tryAcquire會(huì)嘗試去獲取一個(gè)信號(hào)量,如果獲取不到 // 則什么都不會(huì)發(fā)生,走接下來的邏輯 // if (semaphore.tryAcquire(1)) { // test(i); // semaphore.release();//釋放一個(gè)信號(hào)量 // } semaphore.acquire();//獲取一個(gè)信號(hào)量 test(i); semaphore.release();//釋放一個(gè)信號(hào)量 } catch (Exception e) { log.error("exception", e); } }); } log.info("finished"); exec.shutdown(); } public static void test(int i) throw Exception{ log.info("thread: {}", i); } }CyclicBarrier
一個(gè)同步輔助類,它允許一組線程互相等待,直到到達(dá)某個(gè)公共屏障點(diǎn) (common barrier point)。
CyclicBarrier(int parties, Runnable barrierAction)
創(chuàng)建一個(gè)新的 CyclicBarrier,它將在給定數(shù)量的參與者(線程)處于等待狀態(tài)時(shí)啟動(dòng),并在啟動(dòng) barrier 時(shí)執(zhí)行給定的屏障操作,該操作由最后一個(gè)進(jìn)入 barrier 的線程執(zhí)行。
CyclicBarrier(int parties)
創(chuàng)建一個(gè)新的 CyclicBarrier,它將在給定數(shù)量的參與者(線程)處于等待狀態(tài)時(shí)啟動(dòng),但它不會(huì)在啟動(dòng) barrier 時(shí)執(zhí)行預(yù)定義的操作。
int await()
在所有 參與者都已經(jīng)在此 barrier 上調(diào)用 await 方法之前,將一直等待。
int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
在所有 參與者都已經(jīng)在此屏障上調(diào)用 await 方法之前將一直等待,或者超出了指定的等待時(shí)間。
boolean isBroken() : 查詢此屏障是否處于損壞狀態(tài)。
void reset() :
將屏障重置為其初始狀態(tài)。如果所有參與者目前都在屏障處等待,則它們將返回,同時(shí)拋出一個(gè) BrokenBarrierException。注意,在由于其他原因造成損壞 之后,實(shí)行重置可能會(huì)變得很復(fù)雜;此時(shí)需要使用其他方式重新同步線程,并選擇其中一個(gè)線程來執(zhí)行重置。與為后續(xù)使用創(chuàng)建一個(gè)新 barrier 相比,這種方法可能更好一些。
int getNumberWaiting() :返回當(dāng)前在屏障處等待的參與者數(shù)目。此方法主要用于調(diào)試和斷言。
@Self4j public class CyclicBarrierExample { private final static int threadCount = 200; private final static CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> { log.info("callback is running !"); } ); public static void main(String[] arg) { ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i < threadCount; i++) { exec.excute( () -> { final int threadNum = i; try { race(i); } catch (Exception e) { log.error("exception", e); } }); } log.info("finished"); exec.shutdown(); } public static void race(int i) throw Exception{ log.info("thread {} is ready", i); cyclicBarrier.await(); log.info("thread {} is continue", i); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72969.html
摘要:整個(gè)包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執(zhí)行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據(jù)一系列常見的多線程設(shè)計(jì)模式,設(shè)計(jì)了并發(fā)包,其中包下提供了一系列基礎(chǔ)的鎖工具,用以對(duì)等進(jìn)行補(bǔ)充增強(qiáng)。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發(fā)于一世流云專欄:https...
摘要:方法由兩個(gè)參數(shù),表示期望的值,表示要給設(shè)置的新值。操作包含三個(gè)操作數(shù)內(nèi)存位置預(yù)期原值和新值。如果處的值尚未同時(shí)更改,則操作成功。中就使用了這樣的操作。上面操作還有一點(diǎn)是將事務(wù)范圍縮小了,也提升了系統(tǒng)并發(fā)處理的性能。 這是java高并發(fā)系列第21篇文章。 本文主要內(nèi)容 從網(wǎng)站計(jì)數(shù)器實(shí)現(xiàn)中一步步引出CAS操作 介紹java中的CAS及CAS可能存在的問題 悲觀鎖和樂觀鎖的一些介紹及數(shù)據(jù)庫...
摘要:有三種狀態(tài)運(yùn)行關(guān)閉終止。類類,提供了一系列工廠方法用于創(chuàng)建線程池,返回的線程池都實(shí)現(xiàn)了接口。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,在提交新任務(wù),任務(wù)將會(huì)進(jìn)入等待隊(duì)列中等待。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。 這是java高并發(fā)系列第19篇文章。 本文主要內(nèi)容 介紹Executor框架相關(guān)內(nèi)容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...
摘要:的缺點(diǎn)頻繁刷新主內(nèi)存中變量,可能會(huì)造成性能瓶頸不具備操作的原子性,不適合在對(duì)該變量的寫操作依賴于變量本身自己。 作者:畢來生微信:878799579 1. 什么是JUC? JUC全稱 java.util.concurrent 是在并發(fā)編程中很常用的實(shí)用工具類 2.Volatile關(guān)鍵字 1、如果一個(gè)變量被volatile關(guān)鍵字修飾,那么這個(gè)變量對(duì)所有線程都是可見的。2、如果某條線程修...
摘要:概述是從開始提供的一種非阻塞式線程安全鏈表,隸屬于包。當(dāng)許多線程同時(shí)訪問一個(gè)公共集合時(shí),是一個(gè)合適的選擇。程序的一次輸出為該程序?qū)崿F(xiàn)了多線程并發(fā)添加大量元素到一個(gè)公共的鏈表,剛好是的典型使用場(chǎng)景。 Java JUC學(xué)習(xí) - ConcurrentLinkedDeque 詳解 0x00 前言 如何實(shí)現(xiàn)并發(fā)程序,對(duì)于Java以及其他高級(jí)語言來說都是一件并不容易的事情。在大一上學(xué)期的時(shí)候,我們...
閱讀 1641·2021-09-22 15:25
閱讀 1519·2021-09-07 10:06
閱讀 3195·2019-08-30 15:53
閱讀 1099·2019-08-29 13:12
閱讀 3390·2019-08-29 13:07
閱讀 737·2019-08-28 18:19
閱讀 2278·2019-08-27 10:57
閱讀 995·2019-08-26 13:29