網站首頁 編程語言 正文
概述
1、ThreadPoolExecutor作為java.util.concurrent包對外提供基礎實現,以內部線程池的形式對外提供管理任務執行,線程調度,線程池管理等等服務;
2、Executors方法提供的線程服務,都是通過參數設置來實現不同的線程池機制。
3、先來了解其線程池管理的機制,有助于正確使用,避免錯誤使用導致嚴重故障。同時可以根據自己的需求實現自己的線程池
ThreadPoolExecutor 類
構造方法
public ThreadPoolExecutor(
int corePoolSize, //核心線程數量:如果當前運行的線程數量沒有達到 corePoolSize,則新建一個線程,否則加入到任務隊列中
int maximumPoolSize, //最大線程數:當前系統最多存在的線程數
long keepAliveTime, //最大空閑時間:線程空閑的最大時間,超出時間該線程會銷毀;設置allowCodeThreadTimeOut(true/false),可控制核心線程是否銷毀,默認false 表示允許核心線程即使超過最大線程時間也不會銷毀
TimeUnit unit, //時間單位: 線程空閑的最大時間的單位
BlockingQueue<Runnable> workQueue, //任務隊列: 核心線程數量滿了之后,提交的任務加入到隊列中,等待核心線程數減少后再去創建線程;當任務隊列已滿,但沒有達到最大線程數時,則新建非核心線程
ThreadFactory threadFactory, //線程工廠: 自定義線程的創建
RejectedExecutionHandler handler //飽和處理機制:當任務隊列已滿且達到最大線程數時,采取的措施
)
線程池原理
線程池底層使用**堵塞式隊列 BlockingQueue **。
隊列遵從:先進先出,后進后出原則。 阻塞隊列(BlockingQueue)和非阻塞隊列(ConcurrentLinkedQueue )區別:
無界和有界隊列:
ConcurrentLinkedQueue 是無界隊列,不用設置長度,可以隨便存放值(其實是jdk偽造的,最大長度是Integer的最大值) BlockingQueue 是有界隊列,需要設置長度。 注意:如果BlockingQueue 不設置等待時間就是非阻塞隊列
存入:
非阻塞隊列:如果存放超出了隊列總數,添加不進去,就會丟失。 阻塞隊列:如果存放超出了隊列總數,進行等待,直到有隊列出列,或者超時設置的等待時間)
獲取:
非阻塞隊列:如果為空時,返回空。 阻塞隊列:如果為空時,進行等待,直到有新的隊列入列,或者超過設置的等待時間
創建線程池的構造方法
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
- ThreadPoolExecutor
- 參數說明
- 核心線程大小(corePoolSize)
- 最大線程大小(maximumPoolSize)
- 終止時間(keepAliveTime)
- Unit 超時時間
- workQueue 線程容器
自定義線程池
1、編寫任務類
public class MyTask implements Runnable{
//任務id
private int id;
public MyTask(int id){
this.id=id;
}
@Override
public void run() {
String name=Thread.currentThread().getName();
System.out.println("線程:"+name+"-->即將執行任務"+id);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程:"+name+"執行完成"+id);
}
@Override
public String toString() {
return "MyTask{" +
"id=" + id +
'}';
}
}
2、編寫線程類,用于執行任務
public class MyThread extends Thread{
private List<Runnable> tasks;
public MyThread(String name, List<Runnable> tasks){
super(name);
this.tasks=tasks;
}
@Override
public void run() {
while (tasks.size() > 0){
Runnable r= tasks.remove(0);
r.run();
}
}
}
3、編寫線程池類,用于管理線程的執行
public class MyThreadPool {
private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());
/**
* 當前線程數
*/
private int num;
/**
* 核心線程數
*/
private int corePoolSize;
/**
* 最大線程數
*/
private int maxSize;
/**
* 任務隊列數
*/
private int workSize;
public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
this.corePoolSize = corePoolSize;
this.maxSize = maxSize;
this.workSize = workSize;
}
/**
* 提交任務
*/
public void submit(Runnable r){
if (tasks.size()>=workSize && tasks.size() > maxSize){
System.out.println("任務:"+r+"被丟棄了");
}else{
tasks.add(r);
execTask(r);
}
}
public void execTask(Runnable r){
if (corePoolSize > num){
new MyThread("核心線程:"+num,tasks).start();
num++;
}else if(num < maxSize){
new MyThread("非核心線程:"+num,tasks).start();
num++;
}else{
System.out.println("任務:"+r+"被緩存了");
}
}
}
4、測試
public class Demo {
public static void main(String[] args) {
MyThreadPool myThreadPool = new MyThreadPool(2, 4, 20);
for (int i =0;i< 300;i++){
MyTask myTask = new MyTask(i);
myThreadPool.submit(myTask);
}
}
}
以上就是Android開發中ThreadPoolExecutor與自定義線程池;
文末
1、用ThreadPoolExecutor自定義線程池,看線程是的用途,如果任務量不大,可以用無界隊列,如果任務量非常大,要用有界隊列,防止OOM
2、如果任務量很大,還要求每個任務都處理成功,要對提交的任務進行阻塞提交,重寫拒絕機制,改為阻塞提交。保證不拋棄一個任務
3、最大線程數一般設為2N+1最好,N是CPU核數
4、核心線程數,看應用,如果是任務,一天跑一次,設置為0,合適,因為跑完就停掉了,如果是常用線程池,看任務量,是保留一個核心還是幾個核心線程數
5、如果要獲取任務執行結果,用CompletionService,但是注意,獲取任務的結果的要重新開一個線程獲取,如果在主線程獲取,就要等任務都提交后才獲取,就會阻塞大量任務結果,隊列過大OOM,所以最好異步開個線程獲取結果
原文鏈接:https://juejin.cn/post/7168453723591540743
相關推薦
- 2021-12-20 docke自定義網絡之容器互聯_docker
- 2023-03-28 基于Python開發云主機類型管理腳本分享_python
- 2022-07-02 如何對numpy?矩陣進行通道間求均值_python
- 2022-08-11 GoFrame基于性能測試得知grpool使用場景_Golang
- 2023-12-18 SerializationException異常產生原因及解決方案
- 2023-07-14 css 實現塊標簽上下左右居中
- 2022-06-25 pytorch中permute()函數用法實例詳解_python
- 2023-01-03 C++特性之智能指針shared_ptr詳解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支