關於Java併發的常用類回顧

volatile 關鍵字

  • 變量聲明爲volatile,表示這個變量是不穩定的,每次使用都去主存中讀取
  • Volatile 修飾的成員變量在每次被線程訪問時,都強迫從共享內存中重讀該成員變量的值
  • 問題:兩個線程分別讀寫volatile變量,線程A寫入變量,線程B讀取的時候會看到寫入volatile變量之前所有可見的共享變量
  • Volatile一般情況下不能代替sychronized,因爲volatile不能保證操作的原子性,即使只是i++,實際上也是由多個原子操作組成
  • volatile關鍵字用於聲明簡單類型變量,如int、float、 boolean等數據類型。如果這些簡單數據類型聲明爲volatile,對它們的操作就會變成原子級別的。但這有一定的限制:

    • 當變量的值由自身的上一個決定時,如n=n+1、n++ 等,volatile關鍵字將失效
    • 只有當變量的值和自身上一個值無關時對該變量的操作纔是原子級別的,如n = m + 1,這個就是原子級別的

synchronizedList

  • 包裹了普通的ArrayList提供了線程安全的機制,類似Vector,所以到此爲止synchronizedList與Vector的區別就是ArrayList與Vector的增量速度區別,所以需要線程安全操作時,增量比較快的時候推薦使用Vector
  • synchronizedList在迭代的時候,需要開發者自己加上線程鎖控制代碼
  • 因爲迭代器涉及的代碼沒有在java api中沒有加上線程同步代碼

Executor框架

  • Executor 框架包括:線程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable 等。
  • 分類

    • Executors.newCachedThreadPool();
      • Executors.newFixedThreadPool(5);
      • Executors.newSingleThreadExecutor();
      • Executors.newScheduledThreadPool(3);
  • Callble任務

    • Callable 中的 call()方法類似 Runnable 的 run()方法,區別同樣是有返回值,後者沒有
    • Future.get()得到返回結果
  • 自定義線程池,可以用 ThreadPoolExecutor 類創建

    public ThreadPoolExecutor (int corePoolSize, int maximumPoolSize, long         keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue)
    
  • 當有新的任務要處理時,先看線程池中的線程數量是否大於 corePoolSize,再看緩衝隊列 workQueue 是否滿,最後看線程池中的線程數量是否大於 maximumPoolSize。

Lock鎖

  • Lock 接口有 3 個實現它的類:
    • ReentrantLock
    • ReetrantReadWriteLock.ReadLock
    • ReetrantReadWriteLock.WriteLock
  • Java 5 中引入了注入 AutomicInteger、AutomicLong、AutomicReference 等特殊的原子性變量類,它們提供的如:compareAndSet()、incrementAndSet()和getAndIncrement()等方法都使用了 CAS 操作
  • 條件變量Condition實現線程間協作
    • await()、signal()、signalAll()

阻塞隊列

  • 阻塞隊列的接口是 java.util.concurrent.BlockingQueue,它有多個實現類:ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue 等
  • ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。

    • 默認情況下不保證訪問者公平的訪問隊列,概念:先阻塞的消費者線程,可以先從隊列裏獲取元素
  • LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。

  • PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。

    • 默認情況下元素採取自然順序排列,也可以通過比較器comparator來指定元素的排序規則
  • DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。

    • 隊列中的元素必須實現Delayed接口,在創建元素時可以指定多久才能從隊列中獲取當前元素。只有在延遲期滿時才能從隊列中提取元素
  • SynchronousQueue:一個不存儲元素的阻塞隊列。

    • 每一個put操作必須等待一個take操作
  • LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。

  • LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。

    • 相比其他的阻塞隊列,LinkedBlockingDeque多了addFirst,addLast,offerFirst,offerLast,peekFirst,peekLast等方法

阻塞棧

  • 阻塞棧的接口java.util.concurrent.BlockingDeque
  • 多種實現

併發新特性—障礙器 CyclicBarrier

  • 創建一組任務,它們併發地執行工作,指定一個任務,該組任務全部執行結束,這個任務才得以執行

CountDownLatch類

  • 位於java.util.concurrent包下,利用它可以實現類似計數器的功能。比如有一個任務A,它要等待其他4個任務執行完畢之後才能執行,此時就可以利用CountDownLatch來實現這種功能了。

信號量Semaphore

  • 可以通過使用信號量來自定義實現類似 Java 中的 synchronized、wait、notify 機制。
  • 以控制某個資源被同時訪問的任務數,它通過acquire()獲取一個許可,release()釋放一個許可。如果被同時訪問的任務數已滿,則其他 acquire 的任務進入等待狀態,直到有一個任務被 release 掉,它才能得到許可。
  • 注意是對併發訪問的任務數進行監控,而不會保證線程安全

ps

  • CountDownLatch和CyclicBarrier都能夠實現線程之間的等待,只不過它們側重點不同:

        CountDownLatch一般用於某個線程A等待若干個其他線程執行完任務之後,它才執行;

        而CyclicBarrier一般用於一組線程互相等待至某個狀態,然後這一組線程再同時執行;

        CountDownLatch是不能重用的,而CyclicBarrier可以重用。

  • Semaphore其實和鎖有點類似,它一般用於控制對某組資源的訪問權限。

參考

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