1. 程式人生 > >執行緒併發執行緒安全介紹及java.util.concurrent包下類介紹

執行緒併發執行緒安全介紹及java.util.concurrent包下類介紹

執行緒Thread,在Java開發中多執行緒是必不可少的,但是真正能用好的並不多!

首先開啟一個執行緒三種方式

 ①new Thread(Runnable).start()

 ②thread.start();       //thread類必須繼承Thread

 ③Executor pool = Executors.newFixedThreadPool(7);pool.execute(new Runnable() ); //利用執行緒池

在多執行緒併發則一定會帶來執行緒安全的問題,如何解決執行緒安全

執行緒的安全控制有三個級別

• JVM 級別。大多數現代處理器對併發對 某一硬體級別提供支援,通常以 compare-and-swap (CAS)指令形式。CAS 是一種低級別的、細粒度的技術,它允許多個執行緒更新一個記憶體位置,同時能夠檢測其他執行緒的衝突並進行恢復。它是許多高效能併發演算法的基礎。在 JDK 5.0 之前,Java 語言中用於協調執行緒之間的訪問的惟一原語是同步,同步是更重量級和粗粒度的。公開 CAS 可以開發高度可伸縮的併發 Java 類。


    • 低階實用程式類 -- 鎖定和原子類。使用 CAS 作為併發原語,ReentrantLock 類提供與 synchronized 原語相同的鎖定和記憶體語義,然而這樣可以更好地控制鎖定(如計時的鎖定等待、鎖定輪詢和可中斷的鎖定等待)和提供更好的可伸縮性(競爭時的高效能)。大多數開發人員將不再直接使用 ReentrantLock 類,而是使用在 ReentrantLock 類上構建的高階類。


    • 高階實用程式類。這些類實現併發構建塊,每個電腦科學課本中都會講述這些類 -- 訊號、互斥、閂鎖、屏障、交換程式、執行緒池和執行緒安全集合類等。大部分開發人員都可以在應用程式中用這些類,來替換許多同步、 wait() 和 notify() 的使用,從而提高效能、可讀性和正確性。


常見的執行緒安全操作

 ①加鎖同步 synchronized  Lock

wait() notify()執行緒排程 已實現執行的同步

 ThreadLocal區域性變數  每一個執行緒都有一份資料

④Semaphore 訊號量

 ⑤volatile 保證一個變數的執行緒安全 

 等 等

接下來討論集合的多執行緒安全

原始集合框架包含三個介面:List、Map 和 Set。這三種集合是我們平常使用最多的集合,當集合遇到多執行緒時,我們必須要考慮多執行緒的問題,

比如說一個執行緒1不斷讀取集合執行緒2不斷往集合放入資料,這時就會出現問題

我們都知道vector,hashtable是在Java1.0就引入的集合,兩個都是執行緒安全的,但是現在已很少使用,原因就是內部實現的執行緒安全太消耗資源

java.util.concurrent 是什麼?

java.util.concurrent 包含許多執行緒安全、測試良好、高效能的併發構建塊。建立 java.util.concurrent 的目的就是要實現 Collection 框架對資料結構所執行的併發操作。通過提供一組可靠的、高效能併發構建塊,開發人員可以提高併發類的執行緒安全、可伸縮性、效能、可讀性和可靠性,

java.util.concurrent 中有很多執行緒安全集合、執行緒池、訊號和同步工具

要成為執行緒安全的類,在從多個執行緒訪問時,它必須繼續正確執行,而不管執行時環境執行那些執行緒的排程和交叉,且無需對部分呼叫程式碼執行任何其他同步。結果是對執行緒安全物件的操作將用於按固定的整體一致順序出現所有執行緒。

JDK 1.2 中引入的 Collection 框架是一種表示物件集合的高度靈活的框架,它使用基本介面 List、Set 和 Map。通過 JDK 提供每個集合的多次實現(HashMap、Hashtable、TreeMap、WeakHashMap、HashSet、TreeSet、 Vector、ArrayList、LinkedList 等等)。

java.util.concurrent 包添加了多個新的執行緒安全集合類(ConcurrentHashMap、CopyOnWriteArrayList 和CopyOnWriteArraySet)這些類的目的是提供高效能、高度可伸縮性、執行緒安全的基本集合型別版本

通過同步的封裝工廠(Collections.synchronizedMap()、synchronizedList() 和 synchronizedSet()),非執行緒安全集合均可表現為執行緒安全的

java.util 中的執行緒集合仍有一些缺點。例如,在迭代鎖定時,通常需要將該鎖定保留在集合中,否則,會有丟擲 ConcurrentModificationException
的危險。此外,如果從多個執行緒頻繁地訪問集合,則常常不能很好地執行這些類。

JDK 5.0 還提供了兩個新集合介面 -- Queue 和 BlockingQueue。Queue 介面與 List 類似,但它只允許從後面插入,從前面刪除。通過消除 List 的隨機

訪問要求,可以建立比現有 ArrayList 和 LinkedList 實現效能更好的 Queue 實現。因為 List 的許多應用程式實際上不需要隨機訪問,所以Queue 通常

可以替代 List,來獲得更好的效能。

ConcurrentModificationException這個問題我也遇到過,即便加上同步操作依然不能安全的併發操作,問題的根源還是在於Iterator迭代一致性的

原因

弱一致的迭代器
java.util 包中的集合類都返回 fail-fast 迭代器,這意味著它們假設執行緒在集合內容中進行迭代時,集合不會更改它的內容。如果 fail-fast 迭代器檢測到

在迭代過程中進行了更改操作,那麼它會丟擲 ConcurrentModificationException,這是不可控異常。在迭代過程中不更改集合的要求通常會對許多併發
應用程式造成不便。相反,比較好的是它允許併發修改並確保迭代器只要進行合理操作,就可以提供集合的一致檢視,如 java.util.concurrent 集合類中

的迭代器所做的那樣。java.util.concurrent 集合返回的迭代器稱為弱一致的(weakly consistent)迭代器。對於這些類,如果元素自從迭代開始已經刪
且尚未由 next() 方法返回,那麼它將不返回到呼叫者。如果元素自迭代開始已經新增,那麼它可能返回呼叫者,也可能不返回。在一次迭代中,無論

何更改底層集合,元素不會被 返回兩次

可以用兩種方法建立執行緒安全支援資料的 List -- Vector 或封裝 ArrayList 和 Collections.synchronizedList()。

但是java.util.concurrent 包添加了名稱繁瑣的 CopyOnWriteArrayList。

為什麼我們想要新的執行緒安全的List類?為什麼會出現CopyOnWriteArrayList?
簡單的答案是與迭代和併發修改之間的互動有關。使用 Vector 或使用同步的 List 封裝器,返回的迭代器是 fail-fast 的,
這意味著如果在迭代過程中任何其他執行緒修改 List,迭代可能失敗。Vector 的非常普遍的應用程式是儲存通過元件註冊的監聽器的列表。當發生適合的事件時,該元件將在監聽器的列表中迭代,呼叫每個監聽器。

為了防止 ConcurrentModificationException,迭代執行緒必須複製列表或鎖定列表,以便進行整體迭代,而這兩種情況都需要大量的效能成本。CopyOnWriteArrayList 類通過每次新增或刪除元素時建立支援陣列的新副本,避免了這個問題,但是進行中的迭代保持對建立迭代器時的當前副本進行操作。雖然複製也會有一些成本,但 是在許多情況下,迭代要比修改多得多,
在這些情況下,寫入時複製要比其他備用方法具有更好的效能和併發性。


除了CopyOnWriteArrayList,還有CopyOnWriteArraySet、ConcurrentHashMap

ConcurrentLinkedQueue 快速、執行緒安全的、無阻塞 FIFO 佇列

java.util.concurrent除了這些執行緒安全的集合還有執行緒相關的類還有:

①Executor 框架 是java.util.concurrent 包中包含靈活的執行緒池實現,但是更重要的是,它包含用於管理實現 Runnable 的任務的執行的整個框架

②Future 介面允許表示已經完成的任務、正在執行過程中的任務或者尚未開始執行的任務。通過 Future 介面,可以嘗試取消尚未完成的任務,

查詢任務已經完成還是取消了,以及提取(或等待)任務的結果值。

③Semaphore、CyclicBarrier、CountdownLatch 和 Exchanger 類都是同步工具的例子。每個類都有執行緒可以呼叫的方法,

方法是否被阻塞取決於正在使用的特定同步工具的狀態和規則。

Executor 執行緒池的幾種模型

1、newFixedThreadPool建立一個指定工作執行緒數量的執行緒池。每當提交一個任務就建立一個工作執行緒,如果工作執行緒數量達到執行緒池初始的最大數

則將提交的任務存入到池佇列中。
2、newCachedThreadPool建立一個可快取的執行緒池。這種型別的執行緒池特點是: 
3、newSingleThreadExecutor建立一個單執行緒化的Executor,即只建立唯一的工作者執行緒來執行任務,如果這個執行緒異常結束,會有另一個取代它

保證順序執行(我覺得這點是它的特色)。單工作執行緒最大的特點是可保證順序地執行各個任務,並且在任意給定的時間不會有多個執行緒是活動的 。

4、newScheduleThreadPool建立一個定長的執行緒池,而且支援定時的以及週期性的任務執行,類似於Timer。(這種執行緒池原理暫還沒完全瞭解透徹)

ps:就介紹這麼多,都是幹活

相關推薦

執行併發執行安全介紹java.util.concurrent介紹

執行緒Thread,在Java開發中多執行緒是必不可少的,但是真正能用好的並不多! 首先開啟一個執行緒三種方式  ①new Thread(Runnable).start()  ②thread.star

【一】關於java.util.concurrent併發(atomic)

併發類包除了java.util.concurrent之外,還有java.util.concurrent.atomic和java.util.concurrent.lock.java.util.concurrent中主要是一些關於集合框架的併發實現,例如ConcurrentHas

java.util.concurrent執行安全的集合簡介

一、執行緒安全的集合        Java中有很多支援多執行緒併發的集合,比如Hashtable、Vector但是這些“古老”的併發集合效率並不高,一般只支援一個執行緒對其進行讀寫(加鎖是針對整張表

Java執行與高併發:java.util.concurrent

面試官:你用過JUC的哪些工具類? 前面從基礎開始,到執行緒安全的實現、物件的釋出與共享,涉及到很多執行緒安全的類與工具,JDK1

java.util.concurrent(2)-執行

一、概述 java.util.concurrent中有非常方便的執行緒池實現,提供的Executor框架包含用於管理實現Runnable任務,Executors類提供了許多不同型別的Executor實現的靜態工廠方法。二、例項 public class MyTask implements Runnable {

java.util.concurrent(3)-執行間通訊wait/notify和await/signal

1 wait和notify 當呼叫wait()方法時執行緒會放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件呼叫notify()方法後本執行緒才進入物件鎖定池準備 Object的方法:void notify(): 喚醒一個正在等待該物件的執行緒。void noti

java.util.concurrent執行池Executors的使用

執行緒池的概念與Executors類的使用 (1)建立固定大小的執行緒池–當有多個任務時,會先按照執行緒池中的資料執行任務,其他任務處於等待過程中,等執行完這批任務後再執行下批任務。 (2)建立快

為什麼java.util.concurrent 裡沒有併發的ArrayList實現?

原文連結 作者:Stephen C 譯者:鄭旭東  校對:方騰飛 問:JDK 5在java.util.concurrent裡引入了ConcurrentHashMap,在需要支援高併發的場景,我們可以使用它代替HashMap。但是為什麼沒有ArrayList的併發實現呢?難道在多執行緒場景下我們

聊聊高併發(三十)解析java.util.concurrent各個元件(十二) 理解CyclicBarrier柵欄

這篇講講CyclicBarrier柵欄,從它的名字可以看出,它是可迴圈使用的。它的功能和CountDownLatch類似,也是讓一組執行緒等待,然後一起開始往下執行。但是兩者還是有幾個區別 1. 等待的物件不同。CountDownLatch的一組執行緒等待的是一個事件,或者

聊聊高併發(四十)解析java.util.concurrent各個元件(十六) ThreadPoolExecutor原始碼分析

ThreadPoolExecutor是Executor執行框架最重要的一個實現類,提供了執行緒池管理和任務管理是兩個最基本的能力。這篇通過分析ThreadPoolExecutor的原始碼來看看如何設計和實現一個基於生產者消費者模型的執行器。 生產者消費者模型 生產者消費者

Spring Boot介面畫管理Quartz定時任務執行併發執行定時任務

工程程式碼示例   : Spring Boot整合持久化Quartz定時任務管理和介面展示 工程地址  : https://github.com/tjfy1992/SpringBootQuartz 執行方法 Spring Boot工程已經集成了伺

實驗5 結果不唯一的多執行併發執行例項 操作指導

實驗5  結果不唯一的多執行緒併發執行例項 操作指導 變數及函式說明   pthread_t 型別定義:typedef unsigned long int pthread_t; //come from /usr/include/bits/

springboot動態配置定時任務2種方式,整合Quartz多執行併發執行多個定時任務配置

我的專案是採用的idea+gradle+springboot專案構建,下面是springboot實現定時任務所需要的jar包 //定時任務使用 compile group: 'org.quartz-scheduler', name: 'quartz', version:

【技能庫】--批量任務多執行併發執行(324)

擴充套件callable 介面 並且  Futrue<?>  import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists; import com.google.commo

python 實現多執行併發執行 【join函式】

主執行緒啟動一個子執行緒t並等到t執行緒結束後才執行: import threading import time def reading(): for i in range(5): print("reading", i) time.

c++多執行併發執行

算是學到的一個重要知識語音識別中,聲源定位執行緒所需時間很短。在一次while迴圈中,在聲源定位執行緒得到角度並賦值給全域性變數rotate_angle的時候,語音識別還沒完成。當語音識別完成時,rotate_angle早已經在聲源定位執行緒中被賦值,這時語音識別執行緒完可以

兩個執行併發執行以下程式碼,假設a是全域性變數,那麼以下輸出___哪個是可能的?

兩個執行緒併發執行以下程式碼,假設a是全域性變數,那麼以下輸出_哪個是可能的? int a=1; void foo(){ ++a; printf("%d",a); } 解析 假設執行緒x和y同時執行,x和y可隨時被搶佔,a的初始值為1

批量介面多執行併發執行

開發中可能會有這樣的場景,一個功能需要同時完成不相關的多個操作,最後針對多個操作結果統一處理。比如一個查詢功能內部需要同時查詢A、B、C、D四個介面,彙總所有介面查詢內容後返回,一般來說可以逐個查詢彙總即可。 現在問題來了,如介面超時時間限制為3秒,且A、B、C、D四個介面

執行併發執行任務,取結果歸集:Future、FutureTask、CompletionService、CompletableFuture

Future (1)cancle (2)get (3)isCancle (4)isDone 示例: 使用執行緒池提交Callable介面任務,返回Future介面,新增進李斯特,最後遍歷FutureList且內部使用while輪詢,併發獲取結果 package

Java併發:多執行java.util.concurrent併發總結

引言前面已經針對Java多執行緒框架中具體的點介紹了很多了,現在是需要一個概括性總結的時候了,正好從網上找到一張描述java.util.concurrent包組成結構的類圖,正好可以對java多執行緒中