java并发容器
1 并發容器
(1)ConcurrentHashMap 把整個hashmap 分成若干個小的hashmap(segment),每個segment自己加鎖(用ReentrantLock),put的時候采用while(trylock()),tryLock是底層是使用cas競爭資源,會一直等待鎖資源而不會掛起線程,但是也有次數限制,如果try次數限制大于要求,則會調用lock()函數,lock如果失敗則會掛起線程。如果hash的位置是null表明沒沖突,直接放入,如果hash沖突則得到head從而得到entry的list放入next。
*計算size,先給3次機會,不lock所有的Segment,遍歷所有Segment,累加各個Segment的大小得到整個Map的大小,如果某相鄰的兩次計算獲取的所有Segment的更新的次數(每個Segment都有一個modCount變量,這個變量在Segment中的Entry被修改時會加一,通過這個值可以得到每個Segment的更新操作的次數)是一樣的,說明計算過程中沒有更新操作,則直接返回這個值。如果這三次不加鎖的計算過程中Map的更新次數有變化,則之后的計算先對所有的Segment加鎖,再遍歷所有Segment計算Map大小,最后再解鎖所有Segment。
*rehash,new的時候最后一個參數concurrentLevel代表segment數量,如果指定了數量則segment不能增加,rehash的時候只在自己segment里面增加長度,相對于HashMap的resize,ConcurrentHashMap的rehash原理類似,但是Doug Lea為rehash做了一定的優化,避免讓所有的節點都進行復制操作:由于擴容是基于2的冪指來操作,假設擴容前某HashEntry對應到Segment中數組的index為i,數組的容量為capacity,那么擴容后該HashEntry對應到新數組中的index只可能為i或者i+capacity,因此大多數HashEntry節點在擴容前后index可以保持不變?;诖?#xff0c;rehash方法中會定位第一個后續所有節點在擴容后index都保持不變的節點,然后將這個節點之前的所有節點重排即可。
*HashMap,List,Set 都不是線程安全的,可以用Collection.synchronizedMap(new HashMap)這種方法來包裝成線程安全的,但只適合并發量比較少的情況,因為被包裝以后,各種操作函數都加上了sychronized(){},并發情況下并不能同時操作對象。
(2)BlockingQueue 線程共享隊列。可以取數據和加數據,沒有數據時,取數據現場會等待,有數據了再喚醒;滿數據時,加數據現場會等待,有空位置了再喚醒。性能不是太好但是線程共享數據非常好用。
(3)線程池ThreadPoolExcutor? ?線程創建和銷毀都需要消耗cpu,因此需要線程池來循環使用固定線程,線程池核心是把所有活動線程保留起來。頂層接口Excutor,ExcutorService擴展接口,
? ? ?newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
? ? ?newFixedThreadPool 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
? ? ?newScheduledThreadPool 創建一個定長線程池,支持定時及周期性任務執行。
? ? ?newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
? ? ?這幾個實現的根本都是實例化了一個ThreadPoolExcutor,通過參數不同確定生成的具體線程池,是個工廠方法。
? ThreadPoolExecutor(int corePoolSize,//核心線程池大小(標準數量)
? ? int maximumPoolSize ? ? //最多容納多少線程(擴展最大數量)
? ? long ? keepAliveTime ?//空閑時線程存活時間,如果線程數大于corePoolSize,那么多余的線程在超過這個時間以后就會釋放掉。
? ?TimeUnit unit, ?//上面時間的單位
? ? BlockingQueue(Runnable) // 排隊等待隊列,保存多余的任務? ? ? ?)
?所以根據這幾個參數,可以得到
? * ?newCachedThreadPool是實例化一個ThreadPoolExecutor(0,Integer.MaxValue,60l,SECOND,SynchronousQueue<Runnable>()),初始線程為0,提交的任務提交到同步隊列,但這個隊列容量是0,只有線程池拿任務跟程序提交任務同時發生的時候,拿任務和提交任務才會成功,因此這個同步隊列只起了個交換數據的橋接作用。線程池會響應提交失敗的動作,開始創建線程c處理這個任務,超時時間60秒。一般用于耗時較短的任務,任務處理速度要大于提交速度,不然不斷產生新線程內存可能被占滿。
? * ?newFixedThreadPool (int nThread) ?時間上是實例化一個ThreadPoolExecutor (nThread,nThread,0,SECOND,new LinkedBlockingQueue(Runnable)),是個標準線程和最多線程相等(無法擴容)的擁有無限等待隊列的線程池。
? * ?newSingleThreadExecutor其實也是個FixedThreadPool,只是傳入的線程數是1.
(4) ?拒絕策略 ?針對上面的構造函數,最后一個參數其實是RejectedExcutionHandler,并發包提供了幾個策略,也可以自己繼承它實現策略。
? ?ThreadPoolExecutor.AbortPolicy:當線程池中的數量等于最大線程數時拋出java.util.concurrent.RejectedExecutionException異常.?
? ?ThreadPoolExecutor.CallerRunsPolicy():當線程池中的數量等于最大線程數時,讓調用者自己跑這個任務,不用自己的線程池線程。
? ?ThreadPoolExecutor.DiscardOldestPolicy():當線程池中的數量等于最大線程數時,拋棄線程池中工作隊列頭部的任務(即等待時間最久Oldest的任務,也就是隊列第一個拋棄),并執行新傳入的任務
? ThreadPoolExecutor.DiscardPolicy():當線程池中的數量等于最大線程數時,丟棄不能執行的新加任務?
?* 自己可以實現拒絕策略,可以根據個人需求定制行為,比如記錄線程信息等。
(5)ForkJoin forkjoin是java7提供的并發框架,Fork把一個大任務拆成若干個小任務,join是匯總各個小任務的結果最終得到大任務的結果。
? ?分割任務:需要有一個fork類來把大任務分割成子任務,有可能子任務還是很大,所以還需要不停的分割,直到分割出的子任務足夠小。
? ?合并結果:分割的子任務分別放在雙端隊列里,然后幾個啟動線程分別從雙端隊列里獲取任務執行。子任務執行完的結果都統一放在一個隊列里,啟動一個線程從隊列里拿數據,然后合并這些數據。
?*ForkJoinTask:我們要使用ForkJoin框架,必須首先創建一個ForkJoin任務。它提供在任務中執行fork()和join()操作的機制,通常情況下我們不需要直接繼承ForkJoinTask類,而只需要繼承它的子類,Fork/Join框架提供了以下兩個子類:
? ? ?RecursiveAction:用于沒有返回結果的任務。
? ? ?RecursiveTask :用于有返回結果的任務。
?*ForkJoinPool :它實現了工作竊取算法,使得空閑線程能夠主動分擔從別的線程分解出來的子任務,從而讓所有的線程都盡可能處于飽滿的工作狀態,提高執行效率。?工作竊取算法就是,每個線程都有一個任務隊列,這個隊列是雙向隊列,如果一個線程已經處理完自己的隊列,可以從另一個隊列的另一端拿出任務來執行(同一端可能有并發沖突,加鎖會消耗資源)。
2 ThreadLocal ?
? ? ?使用ThreadLocal維護變量時,ThreadLocal為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。在ThreadLocal類中有一個Map,用于存儲每一個線程的變量副本,Map中元素的鍵為線程對象,而值對應線程的變量副本。
? ? ? 在同步機制中,通過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序慎密地分析什么時候對變量進行讀寫,什么時候需要鎖定某個對象,什么時候釋放對象鎖等繁雜的問題,程序設計和編寫難度相對較大。
而ThreadLocal則從另一個角度來解決多線程的并發訪問。ThreadLocal會為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數據的訪問沖突。因為每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。ThreadLocal提供了線程安全的共享對象,在編寫多線程代碼時,可以把不安全的變量封裝進ThreadLocal。
轉載于:https://www.cnblogs.com/lkdirk/p/6691288.html
總結
- 上一篇: 卖零食怎么引流?怎么推广自己的零食产品,
- 下一篇: Maven工程 报 Diamond ty