併發編程之歸納編

JDK併發包

1、ReentrantLock(重入鎖)

ReentrantLock:重入鎖可以完全替換synchronized關鍵字,重入鎖的性能遠遠好於synchronized。
* lock():獲得鎖,如果鎖已經被佔用,則等待
* lockInterruptibly():獲得鎖,但優先響應中斷
* tryLock():嘗試獲得鎖,如果成功,返回true,失敗返回false。該方法不等待,立即返回
* tryLock(long time,TimeUnit unit):在給定時間內嘗試獲得鎖
* unlock():釋放鎖

2、Condition(重入鎖的好搭檔)

Condition:它和wait()和notify()方法的作用大致相同,但是wait()和notify()是和synchronized關鍵字合作使用,而Condition是與重入鎖相關聯的。
* await():方法會使當前線程等待,同時釋放當前鎖,當其他線程使用signal()或signalAll()方法時,線程會重現獲取鎖並繼續執行。或者當前線程被中斷時,也就能跳出等待。者和Object.wait()很相似。
* awaitUninterruptibly():與await()基本相同,但是它並不會在等待過程中響應中斷。
* signal():喚醒一個在等待中的線程,這和Object.notify()很類似。
* signalAll():喚醒所有在等待中的線程。

3、BlockingQueue(信號量)

信號量指定多個線程,同時訪問某一個資源

4、ReadWriteLock(讀寫鎖)

非阻塞
阻塞
  ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  Lock readLock = readWriteLock.readLock();//讀鎖
  Lock writeLock = readWriteLock.writeLock();//寫鎖

5、CountDownLatch(倒計時器)

多線程控制工具類,用來控制線程等待,它可以讓某一個線程等待知道倒計時結束,再開始執行

6、CyclicBarrier(循環柵欄)

CyclicBarrier:和CountDownLatch非常類似,它也可以實現線程間的計數等待,但它的功能比CountDownLatch更加複雜且強大。Cyclic意爲循環,也就是說這個計數器可以反覆使用。比如,假設我們將計數器設置爲10,那麼湊齊第一批10個線程後,計數器就會歸零,然後接着湊齊下一批10個線程,這就是循環柵欄內在的含義。(如:跑步,10個人準備好後一搶令下一起起跑;接着下一批開始。

併發Queue

這裏寫圖片描述

1、ConcurrentLinkedQueue

是一個使用魚高併發場景下的隊列,通過無鎖的方式,實現來高併發狀態下的高性能,通常ConcurrentLinkedQueue性能好於BlockingQueue。它是一個基於鏈接節點的無界線程安全隊列。該隊列的元素遵循先進先出的原則,該隊列不允許null元素
- add()和offer()都是加入元素的方法(在ConcurrentLinkedQueue中沒有任務區別)
- pool()和peek()都是取頭節點,區別在於前者會刪除元素,後者不會

2、BlockingQueue
- ArrayBlockingQueue

基於數組的阻塞隊列實現,在ArrayBlockingQueue內部爲何一個 定長數組,以便緩存隊列中的數據對象,其內部實現讀寫分離,也就意味着生產和消費不能完全並行,長度是需要定義的,可以指定先進先出或者先進後出,也叫有界隊列。

  • LinkedBlockbingQueue

    基於鏈表的阻塞隊列,同ArrayBlockingQueue類似,其內部也維持着一個數據緩衝隊列(該隊列由一個鏈表構成),LinkedBlockbingQueue之所以能夠高效的處理併發數據,是因爲其內部實現採用分離鎖(讀寫分離兩個鎖),從而實現生產者和消費者操作的完全並行運行,是一個無界隊列。

  • PriorityBlockingQueue

    基於優先級的阻塞隊列(有限級的判斷通過構造函數傳入的Compator對象來決定,也就是說傳入隊列的對象必須實現Comparable接口),在實現PriorityBlockingQueue時,內部控制線程同步的鎖採用的是公平鎖,他也是一個無界的隊列。

  • SynchronousQueue

    一種沒有緩衝的隊列,生產者生產的數據會直接被消費者獲取並消費。

  • DelayQueue

    帶有延遲時間的Queue,其中的元素只有當其指定的延遲時間到了,才能夠從隊列中獲取得到該元素。DelayQueue中的元素必須實現Delayed接口,DelayQueue是一個沒有大小限制的隊列。應用場景很多,比如對緩存超時的數據進行移除、任務超時處理、空閒連接的關閉等等

並行模式

Future模式

  Future模式是多線程開發中非常常見的一種設計模式,核心思想是異步調用。
  當我們調用一個函數方法時,如果這個函數執行很慢,那麼我們就要進行等待。但是這個時候,我們可能不着急獲取結果。因此,我們可以讓被調用者立即返回,讓它在後臺慢慢處理這個請求。對於調用者來說,則可以先處理一些其它任務,在真正需要數據的場合再去嘗試獲取需要的數據。
  Future模式雖然無法立即給出你需要的數據,但是它會返回一個契約,以後可以憑藉這個契約重新獲取你所需要的數據。

  • Future模式流程圖模式
    這裏寫圖片描述

  • 常用的方法

    • V get() 獲取返回對象
    • V get(long timeout, TimeUnit unit) 獲取返回對象,可以設置超時實際
    • boolean isDone() 是否已完成
    • boolean isCancelled() 是否已取消
    • boolean cancel(boolean mayInterruptIfRunning) 取消任務

    Msater-Worker模式

    Master-Worker模式時常用的並行計算模式,它的核心思想是系統由兩類進程協助工作:Master進程和Worker進程。Master負責接受和分配任務,Worker負責處理子任務。當各個Worker子進程處理完成後,會將結果返回給Master,由Master做歸納和總結。其好處是能將一個大任務分解成若干個小任務,並行執行,從而提高系統的吞吐量。

這裏寫圖片描述

線程池

爲了避免系統頻繁地創建和銷燬線程,我們可以讓創建的線程進行復用。和數據庫鏈接池類似,在線程池中,總有那麼幾個活躍線程。當你需要使用線程時,可以從池中隨便拿一個koxian線程,當完成工作時,並不着急關閉線程,而是將這個線程退回到池中,方便其它線程使用。
推薦參考一篇總結不錯的文章:Java Executor併發框架

Executor框架:提供各種類型的線程池創建
* newFixedThreadPool

//方法返回一個固定數量的線程池,該線程池中的線程數量始終不變。當又一個新的任務提交時,線程池中如有空閒線程,則立即執行。若沒有,則新的任務會被暫存在一個任務隊列中,待有線程空閒時,便處理在任務隊列中的任務。
public static ExecutorService newFixedThreadPool(int nThreads) 
  • newSingleThreadExecutor
//該方法返回只有一個線程的線程池,若多於一個任務被提交到該線程池,任務會被保存在一個任務隊列中,待線程空閒,按先入先出的順序執行隊列中的任務
public static ExecutorService newSingleThreadExecutor()
  • newCachedThreadPool
//該方法返回一個可根據實際情況調整線程數量的線程池。線程池的數量不確定,但若有空閒線程可以複用,則會優先使用可複用的線程。若所有線程均在工作,又有新的任務提交,則會創建新的線程處理任務。所有線程在當前任務執行完畢後,將返回線程池進行復用。
public static ExecutorService newCachedThreadPool() 
  • newSingleThreadScheduledExecutor
//該方法返回一個ScheduledExecutorService對象,線程池大小爲1.ScheduledExecutorService接口在ExecutorService接口上擴展了在給定時間執行某任務的功能,如在某個固定的延時之後執行,或者週期性執行某個任務。
public static ScheduledExecutorService newSingleThreadScheduledExecutor()
  • ScheduledExecutorService
 //該方法也返回一個ScheduledExecutorService對象,但該線程池可以指定線程數量
 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

ScheduledExecutorService:對線程進行調度

ScheduledExecutorService接口在ExecutorService接口上擴展了在給定時間執行某任務的功能,如在某個固定的延時之後執行,或者週期性執行某個任

  • scheduleAtFixedRate

    //任務調度的頻率是一定的,它是以上一個任務開始執行時間爲七點,之後的period時間,調度下一次任務。 注:如果任務時間比period長,則任務結束後馬上執行。
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,   //任務
                                                  long initialDelay, //第一次任務執行的延時時間
                                                  long period,  //週期時間
                                                  TimeUnit unit); //時間單位
    • scheduleWithFixedDelay
      //在上一個任務結束後,再經過delay時間進行調度。
      public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, //任務
                                                       long initialDelay,//第一次任務執行的延時時間
                                                       long delay, //延時時間:上一次執行完成到下一次執行開始的時間間隔
                                                       TimeUnit unit); //時間單位

待續……….

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章