Java併發容器、框架、工具類

1. 併發容器

1.1 讀寫分離的CopyOnWriteArrayList

線程安全、讀操做無鎖的ArrayList。html

基本思想:當咱們往一個容器添加元素的時候,不直接往當前容器添加,而是先將當前容器進行Copy,複製出一個新的容器,而後新的容器裏添加元素,添加完元素以後,再將原容器的引用指向新的容器。這樣作的好處是咱們能夠對CopyOnWrite容器進行併發的讀,而不須要加鎖,由於當前容器不會添加任何元素。因此CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不一樣的容器。java

CopyOnWrite併發容器用於讀多寫少的併發場景。缺點:(1)內存佔用問題;(2)只能保證數據的最終一致性,不能保證數據的實時一致性。面試

深刻分析可參考:併發編程網-聊聊併發-Java中的Copy-On-Write容器編程

1.2 讀寫分離的CopyOnWriteArraySet

基於CopyOnWriteArrayList實現,原理相似,add操做要遍歷數組以免添加劇復元素。數組

2. 併發工具類

2.1 等待多線程完成的CountDownLatch

等待多線程完成的CountDownLatch,實現異步轉同步操做。安全

深刻分析可參考:併發編程網-併發工具類(一)等待多線程完成的CountDownLatch多線程

2.2 同步屏障CyclicBarrier

比CountDownLatch更強大,當await的數量到達指定數量後,才繼續往下執行。通俗點講就是:讓一組線程到達一個屏障時被阻塞,直到最後一個線程到達屏障時,屏障纔會開門,全部被屏障攔截的線程纔會繼續運行。多用於多線程計算數據,最後合併計算結果的場景。併發

深刻分析可參考:程序猿DD-死磕Java併發:J.U.C之併發工具類:CyclicBarrier異步

2.3 控制併發線程數的Semphore

控制某資源被同時訪問個數,是對鎖的擴展,指定多個線程訪問某一資源。對於臨界區管理代碼,程序會限制同時執行這段代碼的線程數。ide

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * Semaphore實現限流案例
 */
public class Main {
    /**
     * 申請信號量准入數,即同時能申請多少個許可
     */
    static Semaphore semaphore = new Semaphore(10);

    public static void main(String[] args) throws Exception {
        final Executor executor = Executors.newFixedThreadPool(1000);
        for (int i = 0; i < 2000; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    executor();
                }
            });
        }
    }
    public static void executor() {
        try {
            if (semaphore.getQueueLength() > 10) {
                System.out.println("wait...");
                return;
            }
            /**
             * 嘗試得到一個許可,若存在可用資源,直接返回
             * 不然進入等待隊列,不斷嘗試得到資源,而tryAcquire不會等待
             */
            semaphore.acquire();
            // 模擬耗時的業務邏輯
            Thread.sleep(1000);
            System.out.println("run...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 將信號量釋放,以便其餘請求能夠得到空閒資源
            semaphore.release();
        }
    }

}

2.4 線程間交換數據的Exchanger

交換者是用於線程間協做的工具類,用於線程間的數據交換,它提供一個同步點,在這個同步點,兩個線程能夠交換彼此的數據。

深刻分析能夠參考:芋道源碼-【死磕 Java 併發】—– J.U.C 之併發工具類:Exchanger

2.5 異步任務FutureTask

五月的倉頡-Java多線程21:多線程下的其餘組件之CyclicBarrier、Callable、Future和FutureTask

2.6 線程訪問隔離ThreadLocal

歸納起來講,對於多線程資源共享的問題,同步機制採用了「以時間換空間」的方式,而ThreadLocal採用了「以空間換時間」的方式。前者僅提供一份變量,讓不一樣的線程排隊訪問,然後者爲每個線程都提供了一份變量,所以能夠同時訪問而互不影響。

程序猿DD-「圖解」ThreadLocal 在併發問題中的應用(原理剖析、InheritableThreadLocal)

佔小狼的博客-面試官再問你ThreadLocal,你就這樣「懟」回去(使用場景及最佳實踐)

相關文章
相關標籤/搜索