Android開發(fā)ThreadPoolExecutor與自定義線程池詳解
概述
1、ThreadPoolExecutor作為java.util.concurrent包對外提供基礎(chǔ)實現(xiàn),以內(nèi)部線程池的形式對外提供管理任務(wù)執(zhí)行,線程調(diào)度,線程池管理等等服務(wù);
2、Executors方法提供的線程服務(wù),都是通過參數(shù)設(shè)置來實現(xiàn)不同的線程池機制。
3、先來了解其線程池管理的機制,有助于正確使用,避免錯誤使用導(dǎo)致嚴重故障。同時可以根據(jù)自己的需求實現(xiàn)自己的線程池
ThreadPoolExecutor 類
構(gòu)造方法
public ThreadPoolExecutor( int corePoolSize, //核心線程數(shù)量:如果當(dāng)前運行的線程數(shù)量沒有達到 corePoolSize,則新建一個線程,否則加入到任務(wù)隊列中 int maximumPoolSize, //最大線程數(shù):當(dāng)前系統(tǒng)最多存在的線程數(shù) long keepAliveTime, //最大空閑時間:線程空閑的最大時間,超出時間該線程會銷毀;設(shè)置allowCodeThreadTimeOut(true/false),可控制核心線程是否銷毀,默認false 表示允許核心線程即使超過最大線程時間也不會銷毀 TimeUnit unit, //時間單位: 線程空閑的最大時間的單位 BlockingQueue<Runnable> workQueue, //任務(wù)隊列: 核心線程數(shù)量滿了之后,提交的任務(wù)加入到隊列中,等待核心線程數(shù)減少后再去創(chuàng)建線程;當(dāng)任務(wù)隊列已滿,但沒有達到最大線程數(shù)時,則新建非核心線程 ThreadFactory threadFactory, //線程工廠: 自定義線程的創(chuàng)建 RejectedExecutionHandler handler //飽和處理機制:當(dāng)任務(wù)隊列已滿且達到最大線程數(shù)時,采取的措施 )
線程池原理
線程池底層使用**堵塞式隊列 BlockingQueue **。
隊列遵從:先進先出,后進后出原則。 阻塞隊列(BlockingQueue)和非阻塞隊列(ConcurrentLinkedQueue )區(qū)別:
無界和有界隊列:
ConcurrentLinkedQueue 是無界隊列,不用設(shè)置長度,可以隨便存放值(其實是jdk偽造的,最大長度是Integer的最大值) BlockingQueue 是有界隊列,需要設(shè)置長度。 注意:如果BlockingQueue 不設(shè)置等待時間就是非阻塞隊列
存入:
非阻塞隊列:如果存放超出了隊列總數(shù),添加不進去,就會丟失。 阻塞隊列:如果存放超出了隊列總數(shù),進行等待,直到有隊列出列,或者超時設(shè)置的等待時間)
獲取:
非阻塞隊列:如果為空時,返回空。 阻塞隊列:如果為空時,進行等待,直到有新的隊列入列,或者超過設(shè)置的等待時間
創(chuàng)建線程池的構(gòu)造方法
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
- ThreadPoolExecutor
- 參數(shù)說明
- 核心線程大?。╟orePoolSize)
- 最大線程大小(maximumPoolSize)
- 終止時間(keepAliveTime)
- Unit 超時時間
- workQueue 線程容器
自定義線程池
1、編寫任務(wù)類
public class MyTask implements Runnable{
//任務(wù)id
private int id;
public MyTask(int id){
this.id=id;
}
@Override
public void run() {
String name=Thread.currentThread().getName();
System.out.println("線程:"+name+"-->即將執(zhí)行任務(wù)"+id);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程:"+name+"執(zhí)行完成"+id);
}
@Override
public String toString() {
return "MyTask{" +
"id=" + id +
'}';
}
}
2、編寫線程類,用于執(zhí)行任務(wù)
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、編寫線程池類,用于管理線程的執(zhí)行
public class MyThreadPool {
private List<Runnable> tasks = Collections.synchronizedList(new LinkedList<>());
/**
* 當(dāng)前線程數(shù)
*/
private int num;
/**
* 核心線程數(shù)
*/
private int corePoolSize;
/**
* 最大線程數(shù)
*/
private int maxSize;
/**
* 任務(wù)隊列數(shù)
*/
private int workSize;
public MyThreadPool(int corePoolSize, int maxSize, int workSize) {
this.corePoolSize = corePoolSize;
this.maxSize = maxSize;
this.workSize = workSize;
}
/**
* 提交任務(wù)
*/
public void submit(Runnable r){
if (tasks.size()>=workSize && tasks.size() > maxSize){
System.out.println("任務(wù):"+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("任務(wù):"+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開發(fā)中ThreadPoolExecutor與自定義線程池;
文末
1、用ThreadPoolExecutor自定義線程池,看線程是的用途,如果任務(wù)量不大,可以用無界隊列,如果任務(wù)量非常大,要用有界隊列,防止OOM
2、如果任務(wù)量很大,還要求每個任務(wù)都處理成功,要對提交的任務(wù)進行阻塞提交,重寫拒絕機制,改為阻塞提交。保證不拋棄一個任務(wù)
3、最大線程數(shù)一般設(shè)為2N+1最好,N是CPU核數(shù)
4、核心線程數(shù),看應(yīng)用,如果是任務(wù),一天跑一次,設(shè)置為0,合適,因為跑完就停掉了,如果是常用線程池,看任務(wù)量,是保留一個核心還是幾個核心線程數(shù)
5、如果要獲取任務(wù)執(zhí)行結(jié)果,用CompletionService,但是注意,獲取任務(wù)的結(jié)果的要重新開一個線程獲取,如果在主線程獲取,就要等任務(wù)都提交后才獲取,就會阻塞大量任務(wù)結(jié)果,隊列過大OOM,所以最好異步開個線程獲取結(jié)果
以上就是Android開發(fā)ThreadPoolExecutor與自定義線程池詳解的詳細內(nèi)容,更多關(guān)于Android ThreadPoolExecutor的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android 使用viewpager實現(xiàn)無限循環(huán)(定時+手動)
這篇文章主要介紹了Android 使用viewpager實現(xiàn)無限循環(huán)(定時+手動)的相關(guān)資料,需要的朋友可以參考下2015-11-11
發(fā)布?Android?library?到?Maven?解析
這篇文章主要介紹了發(fā)布?Android?library到Maven解析,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09
Android實現(xiàn)錄音監(jiān)聽動畫的示例代碼
在很多app種內(nèi)置了語音助手,也存在各種動畫,這篇文章主要為大家詳細介紹了Android實現(xiàn)錄音監(jiān)聽動畫的示例代碼,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
TextView使用SpannableString設(shè)置復(fù)合文本 SpannableString實現(xiàn)TextView的鏈接
這篇文章主要為大家詳細介紹了如何利用SpannableString實現(xiàn)TextView的鏈接效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Android實現(xiàn)類似execel的表格 能回顯并能修改表格內(nèi)容的方法
今天小編就為大家分享一篇Android實現(xiàn)類似execel的表格 能回顯并能修改表格內(nèi)容的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
android 調(diào)用系統(tǒng)的照相機和圖庫實例詳解
android手機有自帶的照相機和圖庫,我們做的項目中有時用到上傳圖片到服務(wù)器,今天做了一個項目用到這個功能,所以把我的代碼記錄下來和大家分享,有需求的朋友可以參考下2012-12-12

