摘要:將屏障重置為其初始狀態。注意,在由于其他原因造成損壞之后,實行重置可能會變得很復雜此時需要使用其他方式重新同步線程,并選擇其中一個線程來執行重置。
安全共享對象策略
1.線程限制 : 一個被線程限制的對象,由線程獨占,并且只能被占有它的線程修改
2.共享只讀 : 一個共享只讀的對象,在沒有額外同步的情況下,可以被多個線程并發訪問,
但是任何線程都不能修改它
3.線程安全對象 : 一個線程安全的對象或則容器,在內部通過同步機制來保證線程安全,
所以其他線程無需額外的同步就可以通過公共接口隨意訪問它
4.被守護對象 : 被守護對象只能通過獲取特定的鎖來訪問
采用synchronized關鍵字同步,缺點 :
不能完成做到線程安全
性能差
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實現FIFO隊列,可以用于構建鎖或則其他同步裝置的基礎框架
利用一個int類型表示狀態
使用方法是基礎
子類通過繼承并通過實現它的方法管理其狀態 { acquire 和 release} 的方法操縱狀態
可以同時實現排他鎖和共享鎖模式(獨占、共享)
常用類CountDownLatch
Semaphore
CyclicBarrier
ReentrantLock
Condition
FutureTask
CountDownLatch是一個同步工具類,它允許一個或多個線程一直等待,直到其他線程執行完后再執行。例如,應用程序的主線程希望在負責啟動框架服務的線程已經啟動所有框架服務之后執行。
CountDownLatch是通過一個計數器來實現的,計數器的初始化值為線程的數量。每當一個線程完成了自己的任務后,計數器的值就相應得減1。當計數器到達0時,表示所有的線程都已完成任務,然后在閉鎖上等待的線程就可以恢復執行任務。
@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計數器為0,則繼續往下執行 latch.await(); // latch的await方法也可以傳入等待時間,等到等待時間后不管有沒完成計數都往下執行 // 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):構造方法,創建具有給定許可數的計數信號量并設置為非公平信號量。
Semaphore(int permits,boolean fair):構造方法,當fair等于true時,創建具有給定許可數的計數信號量并設置為公平信號量。
void acquire():從此信號量獲取一個許可前線程將一直阻塞。
void acquire(int n):從此信號量獲取給定數目許可,在提供這些許可前一直將線程阻塞。
void release():釋放一個許可,將其返回給信號量。就如同車開走返回一個車位。
void release(int n):釋放n個許可。
int availablePermits():獲取當前可用的許可數。
boolean tryAcquire():僅在調用時此信號量存在一個可用許可,才從信號量獲取許可。
boolean tryAcquire(int permits):僅在調用時此信號量中有給定數目的許可時,才從此信號量中獲取這些許可。
boolean tryAcquire(int permits, long timeout, TimeUnit unit) throws InterruptedException
如果在給定的等待時間內此信號量有可用的所有許可,并且當前線程未被 中斷,則從此信號量獲取給定數目的許可。
@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會嘗試去獲取一個信號量,如果獲取不到 // 則什么都不會發生,走接下來的邏輯 // if (semaphore.tryAcquire(1)) { // test(i); // semaphore.release();//釋放一個信號量 // } semaphore.acquire();//獲取一個信號量 test(i); semaphore.release();//釋放一個信號量 } 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
一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。
CyclicBarrier(int parties, Runnable barrierAction)
創建一個新的 CyclicBarrier,它將在給定數量的參與者(線程)處于等待狀態時啟動,并在啟動 barrier 時執行給定的屏障操作,該操作由最后一個進入 barrier 的線程執行。
CyclicBarrier(int parties)
創建一個新的 CyclicBarrier,它將在給定數量的參與者(線程)處于等待狀態時啟動,但它不會在啟動 barrier 時執行預定義的操作。
int await()
在所有 參與者都已經在此 barrier 上調用 await 方法之前,將一直等待。
int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException
在所有 參與者都已經在此屏障上調用 await 方法之前將一直等待,或者超出了指定的等待時間。
boolean isBroken() : 查詢此屏障是否處于損壞狀態。
void reset() :
將屏障重置為其初始狀態。如果所有參與者目前都在屏障處等待,則它們將返回,同時拋出一個 BrokenBarrierException。注意,在由于其他原因造成損壞 之后,實行重置可能會變得很復雜;此時需要使用其他方式重新同步線程,并選擇其中一個線程來執行重置。與為后續使用創建一個新 barrier 相比,這種方法可能更好一些。
int getNumberWaiting() :返回當前在屏障處等待的參與者數目。此方法主要用于調試和斷言。
@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); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72969.html
摘要:整個包,按照功能可以大致劃分如下鎖框架原子類框架同步器框架集合框架執行器框架本系列將按上述順序分析,分析所基于的源碼為。后,根據一系列常見的多線程設計模式,設計了并發包,其中包下提供了一系列基礎的鎖工具,用以對等進行補充增強。 showImg(https://segmentfault.com/img/remote/1460000016012623); 本文首發于一世流云專欄:https...
摘要:方法由兩個參數,表示期望的值,表示要給設置的新值。操作包含三個操作數內存位置預期原值和新值。如果處的值尚未同時更改,則操作成功。中就使用了這樣的操作。上面操作還有一點是將事務范圍縮小了,也提升了系統并發處理的性能。 這是java高并發系列第21篇文章。 本文主要內容 從網站計數器實現中一步步引出CAS操作 介紹java中的CAS及CAS可能存在的問題 悲觀鎖和樂觀鎖的一些介紹及數據庫...
摘要:有三種狀態運行關閉終止。類類,提供了一系列工廠方法用于創建線程池,返回的線程池都實現了接口。線程池的大小一旦達到最大值就會保持不變,在提交新任務,任務將會進入等待隊列中等待。此線程池支持定時以及周期性執行任務的需求。 這是java高并發系列第19篇文章。 本文主要內容 介紹Executor框架相關內容 介紹Executor 介紹ExecutorService 介紹線程池ThreadP...
摘要:的缺點頻繁刷新主內存中變量,可能會造成性能瓶頸不具備操作的原子性,不適合在對該變量的寫操作依賴于變量本身自己。 作者:畢來生微信:878799579 1. 什么是JUC? JUC全稱 java.util.concurrent 是在并發編程中很常用的實用工具類 2.Volatile關鍵字 1、如果一個變量被volatile關鍵字修飾,那么這個變量對所有線程都是可見的。2、如果某條線程修...
摘要:概述是從開始提供的一種非阻塞式線程安全鏈表,隸屬于包。當許多線程同時訪問一個公共集合時,是一個合適的選擇。程序的一次輸出為該程序實現了多線程并發添加大量元素到一個公共的鏈表,剛好是的典型使用場景。 Java JUC學習 - ConcurrentLinkedDeque 詳解 0x00 前言 如何實現并發程序,對于Java以及其他高級語言來說都是一件并不容易的事情。在大一上學期的時候,我們...
閱讀 1625·2021-09-22 15:25
閱讀 1506·2021-09-07 10:06
閱讀 3183·2019-08-30 15:53
閱讀 1090·2019-08-29 13:12
閱讀 3373·2019-08-29 13:07
閱讀 725·2019-08-28 18:19
閱讀 2269·2019-08-27 10:57
閱讀 982·2019-08-26 13:29