JAVA並發編程J.U.C學習總結,java並發編程j.u.c

來源:互聯網
上載者:User

JAVA並發編程J.U.C學習總結,java並發編程j.u.c
前言  

學習了一段時間J.U.C,打算做個小結,個人感覺總結還是非常重要,要不然總感覺知識點零零散散的。

有錯誤也歡迎指正,大家共同進步;

另外,轉載請註明連結,寫篇文章不容易啊,http://www.cnblogs.com/chenpi/p/5614290.html

本文目錄如下,基本上涵蓋了J.U.C的主要內容;

  • JSR 166及J.U.C
  • Executor架構(線程池、 Callable 、Future)
  • AbstractQueuedSynchronizer(AQS架構)
  • Locks & Condition(鎖和條件變數)
  • Synchronizers(同步器)
  • Atomic Variables (原子變數)
  • BlockingQueue(阻塞隊列)
  • Concurrent Collections(並發容器)
  • Fork/Join並行計算架構
  • TimeUnit枚舉
  • 參考資料
JSR 166及J.U.C什麼是JSR:

JSR,全稱 Java Specification Requests, 即Java規範提案, 主要是用於向JCP(Java Community Process)提出新增標準化技術規範的正式請求。每次JAVA版本更新都會有對應的JSR更新,比如在Java 8版本中,其新特性Lambda運算式對應的是JSR 335,新的日期和時間API對應的是JSR 310。

什麼是JSR 166:

當然,本文的關注點僅僅是JSR 166,它是一個關於Java並發編程的規範提案,在JDK中,該規範由java.util.concurrent包實現,是在JDK 5.0的時候被引入的;

另外JDK6引入Deques、Navigable collections,對應的是JSR 166x,JDK7引入fork-join架構,用於並存執行任務,對應的是JSR 166y。

什麼是J.U.C:

即java.util.concurrent的縮寫,該包參考自EDU.oswego.cs.dl.util.concurrent,是JSR 166標準規範的一個實現;

膜拜

那麼,JSR 166以及J.U.C包的作者是誰呢,沒錯,就是Doug Lea大神,挺牛逼的,大神層級任務,貼張照片膜拜下。。。

Executor架構(線程池、 Callable 、Future)什麼是Executor架構

簡單的說,就是一個任務的執行和調度架構,涉及的類如所示:

其中,最頂層是Executor介面,它的定義很簡單,一個用於執行任務的execute方法,如下所示:

public interface Executor {    void execute(Runnable command);}

 另外,我們還可以看到一個Executors類,它是一個工具類(有點類似集合架構的Collections類),用於建立ExecutorServiceScheduledExecutorServiceThreadFactoryCallable對象。

優點:

任務的提交過程與執行過程解耦,使用者只需定義好任務提交,具體如何執行,什麼時候執行不需要關心;

典型步驟:

定義好任務(如Callable對象),把它提交給ExecutorService(如線程池)去執行,得到Future對象,然後調用Future的get方法等待執行結果即可。

什麼是任務:

實現Callable介面或Runnable介面的類,其執行個體就可以成為一個任務提交給ExecutorService去執行;

其中Callable任務可以返回執行結果,Runnable任務無返回結果;

什麼是線程池

通過Executors工具類可以建立各種類型的線程池,如下為常見的四種:

舉個例子(不完整,僅僅示範流程):
ExecutorService executor = Executors.newCachedThreadPool();//建立線程池Task task = new Task(); //建立Callable任務Future<Integer> result = executor.submit(task);//提交任務給線程池執行result.get();//等待執行結果; 可以傳入等待時間參數,指定時間內沒返回的話,直接結束
補充:批量任務的執行方式

方式一:首先定義任務集合,然後定義Future集合用於存放執行結果,執行任務,最後遍曆Future集合擷取結果;

  • 優點:可以依次得到有序的結果;
  • 缺點:不能及時擷取已完成任務的執行結果;

方式二:首先定義任務集合,通過CompletionService封裝ExecutorService,執行任務,然後調用其take()方法去取Future對象

  • 優點:及時得到已完成任務的執行結果
  • 缺點:不能依次得到結果

這裡稍微解釋下,在方式一中,從集合中遍曆的每個Future對象並不一定處於完成狀態,這時調用get()方法就會被阻塞住,所以後面的任務即使已完成也不能得到結果;而方式二中,CompletionService的實現是維護一個儲存Future對象的BlockingQueue,只有當這個Future對象狀態是結束的時候,才會加入到這個Queue中,所以調用take()能從阻塞隊列中拿到最新的已完成任務的結果;

AbstractQueuedSynchronizer (AQS架構)什麼是AQS架構

AQS架構是J.U.C中實現鎖及同步機制的基礎,其底層是通過調用 LockSupport .unpark()和 LockSupport .park()實現線程的阻塞和喚醒。

AbstractQueuedSynchronizer是一個抽象類別,主要是維護了一個int類型的state屬性和一個非阻塞、先進先出的線程等待隊列;其中state是用volatile修飾的,保證線程之間的可見度,隊列的入隊和出對操作都是無鎖操作,基於自旋鎖和CAS實現;另外AQS分為兩種模式:獨佔模式和共用模式,像ReentrantLock是基於獨佔模式模式實現的,CountDownLatch、CyclicBarrier等是基於共用模式。

簡單舉個例子

非公平鎖的lock方法的實現:

 final void lock() {      //CAS操作,如果State為0(表示當前沒有其它線程佔有該鎖),則將它設定為1      if (compareAndSetState(0, 1))               setExclusiveOwnerThread(Thread.currentThread());      else          acquire(1);}

首先是不管先後順序,直接嘗試擷取鎖(非公平的體現),成功的話,直接獨佔訪問;

如果擷取鎖失敗,則調用AQS的acquire方法,在該方法內部會調用tryAcquire方法再次嘗試擷取鎖以及是否可重新進入判斷,如果失敗,則掛起當前線程並加入到等待隊列;

具體可查看ReentrantLock.NonfairSync類和AbstractQueuedSynchronizer類對應的源碼。

Locks & Condition(鎖和條件變數)

先看一下Lock介面提供的主要方法,如下:

  • lock()  等待擷取鎖
  • lockInterruptibly()  可中斷等待擷取鎖,synchronized無法實現可中斷等待
  • tryLock() 嘗試擷取鎖,立即返回true或false
  • tryLock(long time, TimeUnit unit)    指定時間內等待擷取鎖
  • unlock()      釋放鎖
  • newCondition()   返回一個綁定到此 Lock 執行個體上的 Condition 執行個體

關於Lock介面的實現,我們主要是關注以下兩個類:

  • ReentrantLock
  • ReentrantReadWriteLock

ReentrantLock

可重新進入鎖,所謂的可重新進入鎖,也叫遞迴鎖,是指一個線程擷取鎖後,再次擷取該鎖時,不需要重新等待擷取。ReentrantLock分為公平鎖和非公平鎖,公平鎖指的是嚴格按照先來先得的順序排隊等待去擷取鎖,而非公平鎖每次擷取鎖時,是先直接嘗試擷取鎖,擷取不到,再按照先來先得的順序排隊等待。

注意:ReentrantLock和synchronized都是可重新進入鎖。

ReentrantReadWriteLock

可重新進入讀寫鎖,指的是沒有線程進行寫操作時,多個線程可同時進行讀操作,當有線程進行寫操作時,其它讀寫操作只能等待。即“讀-讀能共存,讀-寫不能共存,寫-寫不能共存”。

在讀多於寫的情況下,讀寫鎖能夠提供比排它鎖更好的並發性和輸送量。

Condition

Condition對象是由Lock對象建立的,一個Lock對象可以建立多個Condition,其實Lock和Condition都是基於AQS實現的。

Condition對象主要用於線程的等待和喚醒,在JDK 5之前,線程的等待喚醒是用Object對象的wait/notify/notifyAll方法實現的,使用起來不是很方便;

在JDK5之後,J.U.C包提供了Condition,其中:

Condition.await對應於Object.wait;

Condition.signal 對應於 Object.notify;

Condition.signalAll 對應於 Object.notifyAll;

使用Condition對象有一個比較明顯的好處是一個鎖可以建立多個Condition對象,我們可以給某類線程分配一個Condition,然後就可以喚醒特定類的線程。

Synchronizers(同步器)

J.U.C中的同步器主要用於協助線程同步,有以下四種:

閉鎖 CountDownLatch

閉鎖主要用於讓一個主線程等待一組事件發生後繼續執行,這裡的事件其實就是指CountDownLatch對象的countDown方法。注意其它線程調用完countDown方法後,是會繼續執行的,具體如所示:

在CountDownLatch內部,包含一個計數器,一開始初始化為一個整數(事件個數),發生一個事件後,調用countDown方法,計數器減1,await用於等待計數器為0後繼續執行當前線程;

如:TA主線程會一直等待,直到計數cnt=0,才繼續執行,

可參照之前寫的一篇文章,如下連結,裡面有一個閉鎖的demo樣本。

http://www.cnblogs.com/chenpi/p/5358579.html

柵欄 CyclicBarrier

柵欄主要用於等待其它線程,且會阻塞自己當前線程,所有線程必須同時到達柵欄位置後,才能繼續執行;且在所有線程到達柵欄處,可以觸發執行另外一個預先設定的線程,具體如所示:

在中,T1、T2、T3每調用一次await,計數減減,且在它們調用await方法的時候,如果計數不為0,會阻塞自己的線程;

另外,TA線程會在所有線程到達柵欄處(計數為0)的時候,才開始執行;

可參照之前寫的一篇文章,如下連結,裡面有一個柵欄的demo樣本。

http://www.cnblogs.com/chenpi/p/5358579.html

訊號量Semaphore

訊號量主要用於控制訪問資源的線程個數,常常用於實現資源集區,如資料庫連接池,線程池...

在Semaphore中,acquire方法用於擷取資源,有的話,繼續執行(使用結束後,記得釋放資源),沒有資源的話將阻塞直到有其它線程調用release方法釋放資源;

可參照之前寫的一篇文章,如下連結,裡面有一個訊號量的demo樣本。

http://www.cnblogs.com/chenpi/p/5358579.html

交換器 Exchanger

交換器主要用於線程之間進行資料交換;

當兩個線程都到達共同的同步點(都執行到exchanger.exchange的時刻)時,發生資料交換,否則會等待直到其它線程到達;

Atomic Variables(原子變數)

原子變數主要是方便程式員在多線程環境下,無鎖的進行原子操作;

原子類是基於Unsafe實現的封裝類,核心操作是CAS原子操作;所謂的CAS操作,即compare and swap,指的是將預期值與當前變數的值比較(compare),如果相等則使用新值替換(swap)當前變數,否則不作操作;我們可以摘取一段AtomicInteger的源碼,如下:

    public final boolean compareAndSet(int expect, int update) {        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);    }

在compareAndSwapInt方法中,valueOffset是記憶體位址,expect是預期值,update是更新值,如果valueOffset地址處的值與預期值相等,則將valueOffset地址處的值更新為update值。PS:現代CPU已廣泛支援CAS指令;

在Java中,有四種原子更新方式,如下:

  • 原子方式更新基本類型; AtomicInteger 、 AtomicLong 等
  • 原子方式更新數組; AtomicIntegerArray、 AtomicLongArray等
  • 原子方式更新引用; AtomicReference、 AtomicReferenceFieldUpdater…
  • 原子方式更新欄位; AtomicIntegerFieldUpdater、 AtomicStampedReference(解決CAS的ABA問題)…

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.