本篇文章通讀時間大概3分鐘,希望在三分鐘內的講解,對你有所幫助,一定要認真看並思考,好了。廢話不多數,直接上乾貨,本節內容我們講的是Java的線程池,在講之前我們首先看一下有哪些線程池,這些線程池我們不過多講解,因為我們的關注點是他們是如何實現的,和其運行的原理。
目錄
- 常用線程池列表
- ThreadPoolExecutor
- ThreadFactory線程工廠
- RejectedExecutionHandler拒絕策略
- Queue任務隊列
一. 常用線程池列表
這部分內容,只是幫助你回顧一下線程池的知識,大家重點看方法內的實現
1、構造一個固定線程數目的線程池,配置的corePoolSize與maximumPoolSize大小相同,同時使用了一個無界LinkedBlockingQueue存放阻塞任務,因此多餘的任務將存在再阻塞隊列,不會由RejectedExecutionHandler處理
2、構造一個緩衝功能的線程池,配置corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,keepAliveTime=60s,以及一個無容量的阻塞隊列 SynchronousQueue,因此任務提交之後,將會創建新的線程執行;線程空閒超過60s將會銷燬
3、構造一個只支持一個線程的線程池,配置corePoolSize=maximumPoolSize=1,無界阻塞隊列LinkedBlockingQueue;保證任務由一個線程串行執行
4、構造有定時功能的線程池,配置corePoolSize,無界延遲阻塞隊列DelayedWorkQueue;有意思的是:maximumPoolSize=Integer.MAX_VALUE,由於DelayedWorkQueue是無界隊列,所以這個值是沒有意義的
的內容,知識幫助你回顧一下
二. ThreadPoolExecutor
相信大家從上面的眾多線程池中都已經看到了這個類,因為上面的線程池底層的構造都是由這個類創建的,
那麼我們就開始研究這個類
首先看一下構造方法,關於註釋一定要好好看,每個參數都理解了,那麼你就弄懂了
1. 核心的線程池
2. 最大線程池就是說你定義的線程池運行創建的最大線程數量
3. 空閒時間回收,當這個時間後還沒有任務執行就將線程回收
4. 單位,控制上面時間的單位,可以為秒,或者分鐘
5. 核心線程都已經去執行任務但是,任務還有,那麼久先放到這個隊列裡,就相當於集合
6. 創建線程用戶的線程工廠,裡面只有一個方法就是newThread,你可以自定義線程名
7. 拒絕策略,當任務已經執行不了,你拒絕的策略
三. ThreadFactory
ThreadFactory有什麼用呢? 其實就是一個接口,既然是線程工廠,那麼肯定就是創建線程的了
給當前線程分配名字和線程組方便控制。讀到這裡,有沒有一點啟發呢?
四. 拒絕策略
拒絕策略就是任務實在是已經執行不了,那麼就需要你告訴程序,怎麼樣去拒絕在執行其他任務
ThreadPoolExecutor類裡面是內置了4中拒絕策略,我們一個一個來分析
- 策略-1
用於被拒絕任務的處理程序,它直接在 execute 方法的調用線程中運行被拒絕的任務;如果執行程序已關閉,則會丟棄該任務。如下:
- 策略-2
直接拋出異常
- 策略-3
什麼都不做直接丟棄
- 策略-4
從任務隊列中移除最早的一個,然後將拒絕的任務重新執行
到這裡拒絕策略就說完了,應該都明白了吧,下面我們說下實際中會怎麼用。
如果在任務不是特別多特別重要的情境下,可以在執行拒絕策略發送一個通知事件,通知相關的人查看。
比如以下這種
但是當任務特別重要的時候,比如說銀行處理用戶的轉賬信息更新事物的任務時候,那麼這個任務就比較重要了,不可能用這種的,這種對數據要求高的我們都是用Elastic-Job,這種分佈式任務處理框架,任務會首先落數據庫,然後從數據庫中批量讀取任務執行。感興趣的童鞋可以下去自行了解。
五. 任務隊列
Queue:
分為阻塞隊列和非阻塞隊裡
阻塞隊列一共有四套方法分別用來進行insert、remove和examine,當每套方法對應的操作不能馬上執行時會有不同的反應,下面這個表格就分類列出了這些方法:
- ThrowsException:如果操作不能馬上進行,則拋出異常
- SpecialValue:如果操作不能馬上進行,將會返回一個特殊的值,一般是true或者false
- Blocks:如果操作不能馬上進行,操作會被阻塞
- TimesOut:如果操作不能馬上進行,操作會被阻塞指定的時間,如果指定時間沒執行,則返回一個特殊值,一般是true或者false 需要注意的是,我們不能向BlockingQueue中插入null,否則會報NullPointerException。
- LinkedBlockingQueue 無邊界隊裡
- PriorityBlockingQueue 排序隊列,內部會排序但是要實現排序接口
- SynchronousQueue 同步隊列
- ArrayBlockingQueue 阻塞隊裡,內不是數組,有邊界
- DelayQueue 延遲隊裡
1. Java線程池深度講解(也就是本文)
2. OVAL驗證框架使用
3. ThreadLocal線程隔離深度講解(包含Thread源碼講解,父子本地空間繼承和線程池隔離,最後會講解阿里TransmittableThreadLocal底層實現原理)
4. 分佈式鎖對比(zookeeper鎖和基於redis分佈式鎖)
閱讀更多 東方既白 的文章