網上對Java線程池都有很多非常具體的解析,我概念性進行總結下,如有錯誤,可與我聯系修改。
1.1 ThreadPool Executor
一個線程池包括以下四個基本組成部分:
1、線程池管理器(ThreadPool):用於創建並管理線程池,包括 創建線程池,銷毀線程池,添加新任務;
2、工作線程(PoolWorker):線程池中線程,在沒有任務時處於等待狀態,可以循環的執行任務;
3、任務接口(Task):每個任務必須實現的接口,以供工作線程調度任務的執行,它主要規定了任務的入口,任務執行完后的收尾工作,任務的執行狀態等;
4、任務隊列(taskQueue):用於存放沒有處理的任務。提供一種緩沖機制。
工作方式:
線程池有一個工作隊列,隊列中包含了要分配給各線程的工作。當線程空閑時,就會從隊列中認領工作。由於線程資源的創建與銷毀開銷很大,所以ThreadPool允許線程的重用,減少創建與銷毀的次數,提高效率。
流程圖細節:
1.2 ForkJoinPool Executor
ForkJoinPool組成類:
1,ForkJoinPool:充當fork/join框架里面的管理者,最原始的任務都要交給它才能處理。它負責控制整個fork/join有多少個workerThread,workerThread的創建,激活都是由它來掌控。它還負責workQueue隊列的創建和分配,每當創建一個workerThread,它負責分配相應的workQueue。然后它把接到的活都交給workerThread去處理,它可以說是整個frok/join的容器。
2,ForkJoinWorkerThread:fork/join里面真正干活的"工人",本質是一個線程。里面有一個ForkJoinPool.WorkQueue的隊列存放着它要干的活,接活之前它要向ForkJoinPool注冊(registerWorker),拿到相應的workQueue。然后就從workQueue里面拿任務出來處理。它是依附於ForkJoinPool而存活,如果ForkJoinPool的銷毀了,它也會跟着結束。
3,ForkJoinPool.WorkQueue: 雙端隊列就是它,它負責存儲接收的任務。
4,ForkJoinTask:代表fork/join里面任務類型,我們一般用它的兩個子類RecursiveTask、RecursiveAction。這兩個區別在於RecursiveTask任務是有返回值,RecursiveAction沒有返回值。任務的處理邏輯包括任務的切分都集中在compute()方法里面。
工作方式:
使用一種分治算法,遞歸地將任務分割成更小的子任務,其中閾值可配置,然后把子任務分配給不同的線程執行並發執行,最后再把結果組合起來。該用法常見於數組與集合的運算。
由於提交的任務不一定能夠遞歸地分割成ForkJoinTask,且ForkJoinTask執行時間不等長,所以ForkJoinPool使用一種工作竊取的算法,允許空閑的線程“竊取”分配給另一個線程的工作。由於工作無法平均分配並執行。所以工作竊取算法能更高效地利用硬件資源。
流程圖細節:
1.3 應用場景
ThreadPool:多見於線程並發,阻塞時延比較長的,這種線程池比較常用,一般設置的線程個數根據業務性能要求會比較多。
ForkJoinPool:特點是少量線程完成大量任務,一般用於非阻塞的,能快速處理的業務,或阻塞時延比較少的。