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)不同的線程池機(jī)制。
3、先來了解其線程池管理的機(jī)制,有助于正確使用,避免錯誤使用導(dǎo)致嚴(yán)重故障。同時可以根據(jù)自己的需求實現(xiàn)自己的線程池
ThreadPoolExecutor 類
構(gòu)造方法
public ThreadPoolExecutor( int corePoolSize, //核心線程數(shù)量:如果當(dāng)前運行的線程數(shù)量沒有達(dá)到 corePoolSize,則新建一個線程,否則加入到任務(wù)隊列中 int maximumPoolSize, //最大線程數(shù):當(dāng)前系統(tǒng)最多存在的線程數(shù) long keepAliveTime, //最大空閑時間:線程空閑的最大時間,超出時間該線程會銷毀;設(shè)置allowCodeThreadTimeOut(true/false),可控制核心線程是否銷毀,默認(rèn)false 表示允許核心線程即使超過最大線程時間也不會銷毀 TimeUnit unit, //時間單位: 線程空閑的最大時間的單位 BlockingQueue<Runnable> workQueue, //任務(wù)隊列: 核心線程數(shù)量滿了之后,提交的任務(wù)加入到隊列中,等待核心線程數(shù)減少后再去創(chuàng)建線程;當(dāng)任務(wù)隊列已滿,但沒有達(dá)到最大線程數(shù)時,則新建非核心線程 ThreadFactory threadFactory, //線程工廠: 自定義線程的創(chuàng)建 RejectedExecutionHandler handler //飽和處理機(jī)制:當(dāng)任務(wù)隊列已滿且達(dá)到最大線程數(shù)時,采取的措施 )
線程池原理
線程池底層使用**堵塞式隊列 BlockingQueue **。
隊列遵從:先進(jìn)先出,后進(jìn)后出原則。 阻塞隊列(BlockingQueue)和非阻塞隊列(ConcurrentLinkedQueue )區(qū)別:
無界和有界隊列:
ConcurrentLinkedQueue 是無界隊列,不用設(shè)置長度,可以隨便存放值(其實是jdk偽造的,最大長度是Integer的最大值) BlockingQueue 是有界隊列,需要設(shè)置長度。 注意:如果BlockingQueue 不設(shè)置等待時間就是非阻塞隊列
存入:
非阻塞隊列:如果存放超出了隊列總數(shù),添加不進(jìn)去,就會丟失。 阻塞隊列:如果存放超出了隊列總數(shù),進(jìn)行等待,直到有隊列出列,或者超時設(shè)置的等待時間)
獲取:
非阻塞隊列:如果為空時,返回空。 阻塞隊列:如果為空時,進(jìn)行等待,直到有新的隊列入列,或者超過設(shè)置的等待時間
創(chuàng)建線程池的構(gòu)造方法
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
- ThreadPoolExecutor
- 參數(shù)說明
- 核心線程大小(corePoolSize)
- 最大線程大小(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ù)進(jìn)行阻塞提交,重寫拒絕機(jī)制,改為阻塞提交。保證不拋棄一個任務(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與自定義線程池詳解的詳細(xì)內(nèi)容,更多關(guān)于Android ThreadPoolExecutor的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android ListView下拉刷新上拉自動加載更多DEMO示例
這篇文章主要介紹了Android ListView下拉刷新上拉自動加載更多DEMO示例的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-07-07Android?OpenCV基礎(chǔ)API清晰度亮度識別檢測
這篇文章主要為大家介紹了Android?OpenCV基礎(chǔ)API清晰度亮度識別檢測,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Android應(yīng)用中使用及實現(xiàn)系統(tǒng)“分享”接口實例
為了應(yīng)用的推廣、傳播,很多的應(yīng)用中都有“分享”功能,這篇文章主要介紹了Android應(yīng)用中使用及實現(xiàn)系統(tǒng)“分享”接口實例,有興趣的可以了解一下。2016-12-12Flutter listview如何實現(xiàn)下拉刷新上拉加載更多功能
這篇文章主要給大家介紹了關(guān)于Flutter listview如何實現(xiàn)下拉刷新上拉加載更多功能的相關(guān)資料,對于新聞列表數(shù)據(jù)的更新和加載更多是必不可少的,而實現(xiàn)下拉刷新與上劃加載更多的方式有很多種,需要的朋友可以參考下2021-08-08Android UI設(shè)計與開發(fā)之實現(xiàn)應(yīng)用程序只啟動一次引導(dǎo)界面
這篇文章主要為大家詳細(xì)介紹了Android UI設(shè)計與開發(fā)之實現(xiàn)應(yīng)用程序只啟動一次引導(dǎo)界面,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08android開發(fā)教程之startActivityForResult使用方法
這篇文章主要介紹了android開發(fā)教程之startActivityForResult使用方法,需要的朋友可以參考下2014-03-03