全網最全的並行程式設計最佳學習路線!!(建議收藏)

2021-08-02 15:00:02

大家好,我是冰河~~

今天給小夥伴們帶來一篇我整理了一個月的並行程式設計最佳學習路線,這應該是全網最全的並行程式設計學習路線了吧!希望能夠為小夥伴們帶來實質性的幫助。

如果文章對你有點幫助,還請小夥伴們點贊、收藏、評論、分享呀,讓更多的小夥伴看到,一起進階,一起成長~~

先來看下我花了一個月整理的並行程式設計腦圖吧,這應該是全網最全的了!!

在這裡插入圖片描述

Java記憶體模型(JMM)

執行緒通訊機制

  • 記憶體共用

    • Java採用
  • 訊息傳遞

記憶體模型

  • 重排序

    • 為了程式的效能,處理器、編譯器都會對程式進行重排序處理

    • 條件

      • 在單執行緒環境下不能改變程式執行的結果
      • 存在資料依賴關係的不允許重排序
    • 問題

      • 重排序在多執行緒環境下可能會導致資料不安全
  • 順序一致性

    • 多執行緒環境下的理論參考模型

    • 為程式提供了極強的記憶體可見性保證

    • 特性

      • 一個執行緒中的所有操作必須按照程式的順序來執行
      • 所有執行緒都只能看到一個單一的操作執行順序,不管程式是否同步
      • 每個操作都必須原子執行且立刻對所有執行緒可見
  • happens-before

    • JMM中最核心的理論,保證記憶體可見性

    • 在JMM中,如果一個操作執行的結果需要對另一個操作可見,那麼這兩個操作之間必須存在happens-before關係。

    • 理論

      • 如果一個操作happens-before另一個操作,那麼第一個操作的執行結果將對第二個操作可見,而且第一個操作的執行順序排在第二個操作之前
      • 兩個操作之間存在happens-before關係,並不意味著一定要按照happens-before原則制定的順序來執行。如果重排序之後的執行結果與按照happens-before關係來執行的結果一致,那麼這種重排序並不非法
  • as-if-serial

    • 所有的操作均可以為了優化而被重排序,但是你必須要保證重排序後執行的結果不能被改變

synchronized

  • 同步、重量級鎖

  • 原理

    • synchronized可以保證方法或者程式碼塊在執行時,同一時刻只有一個方法可以進入到臨界區,同時它還可以保證共用變數的記憶體可見性
  • 鎖物件

    • 普通同步方法,鎖是當前範例物件
    • 靜態同步方法,鎖是當前類的class物件
    • 同步方法塊,鎖是括號裡面的物件
  • 實現機制

    • Java物件頭

      • synchronized的鎖就是儲存在Java物件頭中的

      • 包括兩部分資料

        • Mark Word(標記欄位)

          • Mark Word被設計成一個非固定的資料結構以便在極小的空間記憶體儲存儘量多的資料,它會根據物件的狀態複用自己的儲存空間

          • 包括

            • 雜湊碼(HashCode)、GC分代年齡、鎖狀態標誌、執行緒持有的鎖、偏向執行緒 ID、偏向時間戳
        • Klass Pointer(型別指標)

    • monitor

      • Owner

        • 初始時為NULL表示當前沒有任何執行緒擁有該monitor record,當執行緒成功擁有該鎖後儲存執行緒唯一標識,當鎖被釋放時又設定為NULL
  • 鎖優化

    • 自旋鎖

      • 該執行緒等待一段時間,不會被立即掛起,看持有鎖的執行緒是否會很快釋放鎖(迴圈方式)

      • 自旋字數較難控制(-XX:preBlockSpin)

      • 存在理論:執行緒的頻繁掛起、喚醒負擔較重,可以認為每個執行緒佔有鎖的時間很短,執行緒掛起再喚醒得不償失

      • 缺點

        • 自旋次數無法確定
    • 適應性自旋鎖

      • 自旋的次數不再是固定的,它是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態來決定
      • 自旋成功,則可以增加自旋次數,如果獲取鎖經常失敗,那麼自旋次數會減少
    • 鎖消除

      • 若不存在資料競爭的情況,JVM會消除鎖機制

      • 判斷依據

        • 變數逃逸
    • 鎖粗化

      • 將多個連續的加鎖、解鎖操作連線在一起,擴充套件成一個範圍更大的鎖。例如for迴圈內部獲取鎖
    • 輕量級鎖

      • 在沒有多執行緒競爭的前提下,減少傳統的重量級鎖使用作業系統互斥量產生的效能消耗

      • 通過CAS來獲取鎖和釋放鎖

      • 效能依據

        • 對於絕大部分的鎖,在整個生命週期內都是不會存在競爭的
      • 缺點

        • 在多執行緒環境下,其執行效率比重量級鎖還會慢
    • 偏向鎖

      • 為了在無多執行緒競爭的情況下儘量減少不必要的輕量級鎖執行路徑
      • 主要儘可能避免不必須要的CAS操作,如果競爭鎖失敗,則升級為輕量級鎖

volatile

  • 特性

    • volatile可見性:對一個volatile的讀,總可以看到對這個變數最終的寫
    • volatile原子性:volatile對單個讀/寫具有原子性(32位元Long、Double),但是複合操作除外,例如i++;
  • 實現機制

    • 記憶體屏障
  • 記憶體語意

    • 當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共用變數值立即重新整理到主記憶體中
    • 當讀一個volatile變數時,JMM會把該執行緒對應的本地記憶體設定為無效,直接從主記憶體中讀取共用變數
  • 作業系統語意

    • 主記憶體、快取記憶體(執行緒私有)快取一致?

    • 解決方案

      • 通過在匯流排加LOCK#鎖的方式
      • 通過快取一致性協定(MESI協定)
  • 記憶體模型

    • 重排序
    • happens-before

DCL

  • 單例模式

  • DCL

    • 重排序
    • happens-beofre
  • 解決方案

    • volatile方案

      • 禁止重排序
    • 基於類初始化的解決方案

      • 利用classloder的機制來保證初始化instance時只有一個執行緒。JVM在類初始化階段會獲取一個鎖,這個鎖可以同步多個執行緒對同一個類的初始化

並行基礎

AQS

  • AbstractQueuedSynchronizer,同步器,實現JUC核心基礎元件

  • 解決了子類實現同步器時涉及的大量細節問題,例如獲取同步狀態、FIFO同步佇列

  • 採用模板方法模式,AQS實現大量通用方法,子類通過繼承方式實現其抽象方法來管理同步狀態

  • CLH同步佇列

    • FIFO雙向佇列,AQS依賴它來解決同步狀態的管理問題
    • 首節點喚醒,等待佇列加入到CLH同步佇列的尾部
  • 同步狀態獲取與釋放

    • 獨佔式

      • 獲取鎖

        • 獲取同步狀態:acquire
        • 響應中斷:acquireInterruptibly
        • 超時獲取:tryAcquireNanos
      • 釋放鎖

        • release
    • 共用式

      • 獲取鎖

        • acquireShared
      • 釋放鎖

        • releaseShared
  • 執行緒阻塞和喚醒

    • 當有執行緒獲取鎖了,其他再次獲取時需要阻塞,當執行緒釋放鎖後,AQS負責喚醒執行緒

    • LockSupport

      • 是用來建立鎖和其他同步類的基本執行緒阻塞原語
      • 每個使用LockSupport的執行緒都會與一個許可關聯,如果該許可可用,並且可在程序中使用,則呼叫park()將會立即返回,否則可能阻塞。如果許可尚不可用,則可以呼叫 unpark 使其可用
      • park()、unpark()

CAS

  • Compare And Swap,整個JUC體系最核心、最基礎理論

  • 記憶體值V、舊的預期值A、要更新的值B,當且僅當記憶體值V的值等於舊的預期值A時才會將記憶體值V的值修改為B,否則什麼都不幹

  • native中存在四個引數

  • 缺陷

    • 迴圈時間太長

    • 只能保證一個共用變數原子操作

    • ABA問題

      • 解決方案

        • 版本號
        • AtomicStampedReference

ReentrantLock

  • 可重入鎖,是一種遞迴無阻塞的同步機制
  • 比synchronized更強大、靈活的鎖機制,可以減少死鎖發生的概率
  • 分為公平鎖、非公平鎖
  • 底層採用AQS實現,通過內部Sync繼承AQS

ReentrantReadWriteLock

  • 讀寫鎖,兩把鎖:共用鎖:讀鎖、排他鎖:寫鎖
  • 支援公平性、非公平性,可重入和鎖降級
  • 鎖降級:遵循獲取寫鎖、獲取讀鎖在釋放寫鎖的次序,寫鎖能夠降級成為讀鎖

Condition

  • Lock 提供條件Condition,對執行緒的等待、喚醒操作更加詳細和靈活
  • 內部維護一個Condition佇列。當前執行緒呼叫await()方法,將會以當前執行緒構造成一個節點(Node),並將節點加入到該佇列的尾部

並行工具類

CyclicBarrier

  • 它允許一組執行緒互相等待,直到到達某個公共屏障點 (common barrier point)

  • 通俗講:讓一組執行緒到達一個屏障時被阻塞,直到最後一個執行緒到達屏障時,屏障才會開門,所有被屏障攔截的執行緒才會繼續幹活

  • 底層採用ReentrantLock + Condition實現

  • 應用場景

    • 多執行緒結果合併的操作,用於多執行緒計算資料,最後合併計算結果的應用場景

CountDownLatch

  • 在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待

  • 用給定的計數 初始化 CountDownLatch。由於呼叫了 countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的執行緒,await 的所有後續呼叫都將立即返回。這種現象只出現一次——計數無法被重置。如果需要重置計數,請考慮使用 CyclicBarrier。

  • 與CyclicBarrier區別

    • CountDownLatch的作用是允許1或N個執行緒等待其他執行緒完成執行;而CyclicBarrier則是允許N個執行緒相互等待
    • CountDownLatch的計數器無法被重置;CyclicBarrier的計數器可以被重置後使用,因此它被稱為是迴圈的barrier
  • 內部採用共用鎖來實現

Semaphore

  • 號誌

    • 一個控制存取多個共用資源的計數器
  • 從概念上講,號誌維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然後再獲取該許可。每個 release() 新增一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可物件,Semaphore 只對可用許可的號碼進行計數,並採取相應的行動

  • 號誌Semaphore是一個非負整數(>=1)。當一個執行緒想要存取某個共用資源時,它必須要先獲取Semaphore,當Semaphore >0時,獲取該資源並使Semaphore – 1。如果Semaphore值 = 0,則表示全部的共用資源已經被其他執行緒全部佔用,執行緒必須要等待其他執行緒釋放資源。當執行緒釋放資源時,Semaphore則+1

  • 應用場景

    • 通常用於限制可以存取某些資源(物理或邏輯的)的執行緒數目
  • 內部採用共用鎖實現

Exchanger

  • 可以在對中對元素進行配對和交換的執行緒的同步點
  • 允許在並行任務之間交換資料。具體來說,Exchanger類允許在兩個執行緒之間定義同步點。當兩個執行緒都到達同步點時,他們交換資料結構,因此第一個執行緒的資料結構進入到第二個執行緒中,第二個執行緒的資料結構進入到第一個執行緒中

其他

ThreadLocal

  • 一種解決多執行緒環境下成員變數的問題的方案,但是與執行緒同步無關。其思路是為每一個執行緒建立一個單獨的變數副本,從而每個執行緒都可以獨立地改變自己所擁有的變數副本,而不會影響其他執行緒所對應的副本

  • ThreadLocal 不是用於解決共用變數的問題的,也不是為了協調執行緒同步而存在,而是為了方便每個執行緒處理自己的狀態而引入的一個機制

  • 四個方法

    • get():返回此執行緒區域性變數的當前執行緒副本中的值
    • initialValue():返回此執行緒區域性變數的當前執行緒的「初始值」
    • remove():移除此執行緒區域性變數當前執行緒的值
    • set(T value):將此執行緒區域性變數的當前執行緒副本中的值設定為指定值
  • ThreadLocalMap

    • 實現執行緒隔離機制的關鍵
    • 每個Thread內部都有一個ThreadLocal.ThreadLocalMap型別的成員變數,該成員變數用來儲存實際的ThreadLocal變數副本。
    • 提供了一種用鍵值對方式儲存每一個執行緒的變數副本的方法,key為當前ThreadLocal物件,value則是對應執行緒的變數副本
  • 注意點

    • ThreadLocal範例本身是不儲存值,它只是提供了一個在當前執行緒中找到副本值得key
    • 是ThreadLocal包含在Thread中,而不是Thread包含在ThreadLocal中
  • 記憶體漏失問題

    • ThreadLocalMap

      • key 弱參照 value 強參照,無法回收
    • 顯示呼叫remove()

Fork/Join

  • 一個用於並行執行任務的框架, 是一個把大任務分割成若干個小任務,最終彙總每個小任務結果後得到大任務結果的框架

  • 核心思想

    • 「分治」
    • fork分解任務,join收集資料
  • 工作竊取

    • 某個執行緒從其他佇列裡竊取任務來執行
    • 執行塊的執行緒幫助執行慢的執行緒執行任務,提升整個任務效率
    • 佇列要採用雙向佇列
  • 核心類

    • ForkJoinPool

      • 執行任務的執行緒池
    • ForkJoinTask

      • 表示任務,用於ForkJoinPool的任務抽象
    • ForkJoinWorkerThread

      • 執行任務的工作執行緒

Java並行集合

ConcurrentHashMap

  • CAS + Synchronized 來保證並行更新的安全,底層採用陣列+連結串列/紅黑樹的儲存結構

  • 重要內部類

    • Node

      • key-value鍵值對
    • TreeNode

      • 紅黑樹節點
    • TreeBin

      • 就相當於一顆紅黑樹,其構造方法其實就是構造紅黑樹的過程
    • ForwardingNode

      • 輔助節點,用於ConcurrentHashMap擴容操作

      • sizeCtl

        • 控制識別符號,用來控制table初始化和擴容操作的

        • 含義

          • 負數代表正在進行初始化或擴容操作
          • -1代表正在初始化
          • -N 表示有N-1個執行緒正在進行擴容操作
          • 正數或0代表hash表還沒有被初始化,這個數值表示初始化或下一次進行擴容的大小
  • 重要操作

    • initTable

      • ConcurrentHashMap初始化方法

      • 只能有一個執行緒參與初始化過程,其他執行緒必須掛起

      • 建構函式不做初始化過程,初始化真正是在put操作觸發

      • 步驟

        • sizeCtl < 0 表示正在進行初始化,執行緒掛起
        • 執行緒獲取初始化資格(CAS(SIZECTL, sc, -1))進行初始化過程
        • 初始化步驟完成後,設定sizeCtl = 0.75 * n(下一次擴容閾值),表示下一次擴容的大小
    • put

      • 核心思想

        • 根據hash值計算節點插入在table的位置,如果該位置為空,則直接插入,否則插入到連結串列或者樹中
        • 真實情況較為複雜
      • 步驟

        • table為null,執行緒進入初始化步驟,如果有其他執行緒正在初始化,該執行緒掛起
        • 如果插入的當前 i 位置 為null,說明該位置是第一次插入,利用CAS插入節點即可,插入成功,則呼叫addCount判斷是否需要擴容。若插入失敗,則繼續匹配(自旋)
        • 若該節點的hash ==MOVED(-1),表示有執行緒正在進行擴容,則進入擴容程序中
        • 其餘情況就是按照連結串列或者紅黑樹結構插入節點,但是這個過程需要加鎖(synchronized)
    • get

      • 步驟

        • table ==null ;return null
        • 從連結串列/紅黑樹節點獲取
    • 擴容

      • 多執行緒擴容

      • 步驟

        • 構建一個nextTable,其大小為原來大小的兩倍,這個步驟是在單執行緒環境下完成的
        • 將原來table裡面的內容複製到nextTable中,這個步驟是允許多執行緒操作
    • 連結串列轉換為紅黑樹過程

      • 所在連結串列的元素個數達到了閾值 8,則將連結串列轉換為紅黑樹
      • 紅黑樹演演算法
  • 1.8 與 1.7的區別

ConcurrentLinkedQueue

  • 基於連結節點的無邊界的執行緒安全佇列,採用FIFO原則對元素進行排序,內部採用CAS演演算法實現

  • 不變性

    • 在入隊的最後一個元素的next為null
    • 佇列中所有未刪除的節點的item都不能為null且都能從head節點遍歷到
    • 對於要刪除的節點,不是直接將其設定為null,而是先將其item域設定為null(迭代器會跳過item為null的節點)
    • 允許head和tail更新滯後。這是什麼意思呢?意思就說是head、tail不總是指向第一個元素和最後一個元素(後面闡述)
  • head的不變性和可變性

  • tail的不變性和可變性

  • 精妙之處:利用CAS來完成資料操作,同時允許佇列的不一致性,弱一致性表現淋漓盡致

ConcurrentSkipListMap

  • 第三種key-value資料結構:SkipList(跳錶)

  • SkipList

    • 平衡二元樹結構

    • Skip list讓已排序的資料分佈在多層連結串列中,以0-1亂數決定一個資料的向上攀升與否,通過「空間來換取時間」的一個演演算法,
      在每個節點中增加了向前的指標,在插入、刪除、查詢時可以忽略一些不可能涉及到的結點,從而提高了效率

    • 特性

      • 由很多層結構組成,level是通過一定的概率隨機產生的
      • 每一層都是一個有序的連結串列,預設是升序,也可以根據建立對映時所提供的Comparator進行排序,具體取決於使用的構造方法
      • 最底層(Level 1)的連結串列包含所有元素
      • 如果一個元素出現在Level i 的連結串列中,則它在Level i 之下的連結串列也都會出
      • 每個節點包含兩個指標,一個指向同一連結串列中的下一個元素,一個指向下面一層的元素
    • 查詢、刪除、新增

ConcurrentSkipListSet

  • 內部採用ConcurrentSkipListMap實現

atomic

基本型別類

  • 用於通過原子的方式更新基本型別

  • AtomicBoolean

    • 原子更新布林型別
  • AtomicInteger

    • 原子更新整型
  • AtomicLong

    • 原子更新長整型

陣列

  • 通過原子的方式更新陣列裡的某個元素

  • AtomicIntegerArray

    • 原子更新整型陣列裡的元素
  • AtomicLongArray

    • 原子更新長整型陣列裡的元素
  • AtomicReferenceArray

    • 原子更新參照型別陣列裡的元素

參照型別

  • 如果要原子的更新多個變數,就需要使用這個原子更新參照型別提供的類

  • AtomicReference

    • 原子更新參照型別
  • AtomicReferenceFieldUpdater

    • 原子更新參照型別裡的欄位
  • AtomicMarkableReference

    • 原子更新帶有標記位的參照型別

欄位類

  • 如果我們只需要某個類裡的某個欄位,那麼就需要使用原子更新欄位類

  • AtomicIntegerFieldUpdater

    • 原子更新整型的欄位的更新器
  • AtomicLongFieldUpdater

    • 原子更新長整型欄位的更新器
  • AtomicStampedReference

    • 原子更新帶有版本號的參照型別

阻塞佇列

ArrayBlockingQueue

  • 一個由陣列實現的FIFO有界阻塞佇列

  • ArrayBlockingQueue有界且固定,在建構函式時確認大小,確認後不支援改變

  • 在多執行緒環境下不保證「公平性」

  • 實現

    • ReentrantLock
    • Condition

LinkedBlockingQueue

  • 基於連結,無界的FIFO阻塞佇列

PriorityBlockingQueue

  • 支援優先順序的無界阻塞佇列

  • 預設情況下元素採用自然順序升序排序,可以通過指定Comparator來對元素進行排序

  • 二元堆積

    • 分類

      • 最大堆

        • 父節點的鍵值總是大於或等於任何一個子節點的鍵值
      • 最小堆

        • 父節點的鍵值總是小於或等於任何一個子節點的鍵值
    • 新增操作則是不斷「上冒」,而刪除操作則是不斷「下掉」

  • 實現

    • ReentrantLock + Condition
    • 二元堆積

DelayQueue

  • 支援延時獲取元素的無界阻塞佇列

  • 應用

    • 快取:清掉快取中超時的快取資料
    • 任務超時處理
  • 實現

    • ReentrantLock + Condition
    • 根據Delay時間排序的優先順序佇列:PriorityQueue
  • Delayed介面

    • 用來標記那些應該在給定延遲時間之後執行的物件
    • 該介面要求實現它的實現類必須定義一個compareTo 方法,該方法提供與此介面的 getDelay 方法一致的排序。

SynchronousQueue

  • 一個沒有容量的阻塞佇列

  • 應用

    • 交換工作,生產者的執行緒和消費者的執行緒同步以傳遞某些資訊、事件或者任務
  • 難搞懂,與Exchanger 有一拼

LinkedTransferQueue

  • 連結串列組成的的無界阻塞佇列

  • 相當於ConcurrentLinkedQueue、SynchronousQueue (公平模式下)、無界的LinkedBlockingQueues等的超集

  • 預佔模式

    • 有就直接拿走,沒有就佔著這個位置直到拿到或者超時或者中斷

LinkedBlockingDeque

  • 由連結串列組成的雙向阻塞佇列

  • 容量可選,在初始化時可以設定容量防止其過度膨脹,如果不設定,預設容量大小為Integer.MAX_VALUE

  • 運用

    • 「工作竊取」模式

執行緒池

好處

  • 降低資源消耗

    • 通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗
  • 提高響應速度

    • 當任務到達時,任務可以不需要等到執行緒建立就能立即執行
  • 提高執行緒的可管理性

    • 進行統一分配、調優和監控

Executor

  • Executors

    • 靜態工廠類,提供了Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 、Callable 等類的靜態工廠方法
  • ThreadPoolExecutor

    • 引數含義

      • corePoolSize

        • 執行緒池中核心執行緒的數量
      • maximumPoolSize

        • 執行緒池中允許的最大執行緒數
      • keepAliveTime

        • 執行緒空閒的時間
      • unit

        • keepAliveTime的單位
      • workQueue

        • 用來儲存等待執行的任務的阻塞佇列

        • 使用的阻塞佇列

          • ArrayBlockingQueue
          • LinkedBlockingQueue
          • SynchronousQueue
          • PriorityBlockingQueue
      • threadFactory

        • 用於設定建立執行緒的工廠
        • DefaultThreadFactory
      • handler

        • RejectedExecutionHandler,執行緒池的拒絕策略

        • 分類

          • AbortPolicy:直接丟擲異常,預設策略
          • CallerRunsPolicy:用呼叫者所在的執行緒來執行任務
          • DiscardOldestPolicy:丟棄阻塞佇列中靠最前的任務,並執行當前任務
          • DiscardPolicy:直接丟棄任務
    • 執行緒池分類

      • newFixedThreadPool

        • 可重用固定執行緒數的執行緒池

        • 分析

          • corePoolSize和maximumPoolSize一致
          • 使用「無界」佇列
            LinkedBlockingQueue
          • maximumPoolSize、keepAliveTime、
            RejectedExecutionHandler
            無效
      • newCachedThreadPool

        • 使用單個worker執行緒的Executor

        • 分析

          • corePoolSize和maximumPoolSize被設定為1
          • 使用LinkedBlockingQueue作為workerQueue
      • newSingleThreadExecutor

        • 會根據需要建立新執行緒的執行緒池

        • 分析

          • corePoolSize被設定為0
          • maximumPoolSize被設定為Integer.MAX_VALUE
          • SynchronousQueue作為WorkerQueue
          • 如果主執行緒提交任務的速度高於maximumPool中執行緒處理任務的速度時,CachedThreadPool會不斷建立新執行緒 ,可能會耗盡CPU和記憶體資源
    • 任務提交

      • Executor.execute()
      • ExecutorService.submit()
    • 任務執行

      • 執行流程
    • 執行緒池調優

      • 兩種模型
    • 執行緒池監控

  • ScheduledThreadPoolExecutor

    • 繼承自ThreadPoolExecutor
    • 給定的延遲之後執行任務,或者定期執行任務
    • 內部使用DelayQueue來實現 ,會把排程的任務放入DelayQueue中。DelayQueue內部封裝PriorityQueue,這個PriorityQueue會對佇列中的ScheduledFutureTask進行排序

Future

  • 非同步計算

  • Future

    • 提供操作

      • 執行任務的取消
      • 查詢任務是否完成
      • 獲取任務的執行結果
  • FutureTask

    • 實現RunnableFuture介面,既可以作為Runnable被執行,也可以作為Future得到Callable的返回值
    • 內部基於AQS實現

寫在最後

如果你想進大廠,想升職加薪,或者對自己現有的工作比較迷茫,都可以私信我交流,希望我的一些經歷能夠幫助到大家~~

推薦閱讀:

好了,今天就到這兒吧,小夥伴們點贊、收藏、評論,一鍵三連走起呀,我是冰河,我們下期見~~