在Java開發(fā)中蔑担,多線程執(zhí)行任務(wù)是很常見的露氮,Java也提供了線程類Thread來讓我們方便創(chuàng)建一個線程如下代碼所示
new Thread(){
@Override
public void run() {
.....
}
}.start();
-
這樣創(chuàng)建新的線程有幾個缺點
- 每次要開啟新的線程都需要創(chuàng)建一個,性能差
- 線程隨意創(chuàng)建钟沛,缺乏統(tǒng)一的管理
- 不能做到線程的中斷
處理上面的這些問題畔规,我們就需要使用線程池來管理線程。
Java SE5d的java.util.concurrent包 提供了Executor(執(zhí)行器)來管理線程對象恨统。Executor是一個接口叁扫,而ExecutorService繼承了Excutor接口三妈,ExecutorService是一個具有生命周期的Executor,它知道如何構(gòu)建恰當(dāng)?shù)纳舷挛膩韴?zhí)行Runnable對象莫绣。而ExecutorService對象是使用Executors的靜態(tài)方法得到Java中的線程池
//Executor接口實現(xiàn)
public interface Executor {
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* accepted for execution
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
}
-
Java 的四種線程池
-Java中為我們提供了四種線程池畴蒲,他們分別是FixedThreadPool、CachedThreadPool对室、ScheduledThreadPool模燥、SingleThreadExector
-
FixedThreadPool
- 創(chuàng)建方式為使用Executors的newFixedThreadPool()方法來創(chuàng)建,這種線程池的線程數(shù)量是固定的掩宜,可以看到他的靜態(tài)方法需要傳入線程的數(shù)量蔫骂,在空閑狀態(tài)下不會被系統(tǒng)回收,除非它被關(guān)閉了牺汤。當(dāng)它的所有線程都在執(zhí)行任務(wù)的時候辽旋,新加入的線程就會出來等待狀態(tài),等到有線程空閑檐迟,新任務(wù)才會被執(zhí)行,如果新任務(wù)加入時線程池中有空閑的線程补胚,則意味著它可以快速響應(yīng)處理任務(wù)。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } /* * 獲取使用方法 */ Runnable r=new Runnable(){ @Override run(){ ..... } } ExecutorService executor = Executors.newFixedThreadPool(2); executor.execute(r)追迟;
-
CachedThreadPool
創(chuàng)建方式為使用Executors的newCachedThreadPool()方法來創(chuàng)建溶其,由其靜態(tài)方法可以看出,他的線程數(shù)是Integer.MAX_VALUE敦间,可以說他的線程數(shù)是無限大瓶逃,也就是說只要有任務(wù),線程就會立即執(zhí)行每瞒,但是它的每一個線程在空閑狀態(tài)下是有超時機制的金闽,這個時間為60秒纯露,只要線程空閑時間超過60秒該線程就會被回收剿骨,如果所有的線程都處于由空閑狀態(tài)并且超過了60秒,則相當(dāng)于線程池中沒有任何埠褪,線程浓利,也就是說這時的線程池是不占用任何資源的,所以這個線程池比較適合執(zhí)行大量的耗時較少的任務(wù)
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } /* * 獲取使用方法 */ Runnable r=new Runnable(){ @Override run(){ ..... } } ExecutorService executor = Executors.newCachedThreadPool(); executor.execute(r)钞速;
-
ScheduledThreadPool
創(chuàng)建方式為使用Executors的newCachedThreadPool()方法來創(chuàng)建贷掖,這種線程池的核心線程數(shù)是固定的,而非核心線程數(shù)據(jù)是沒有限制的渴语,并且當(dāng)非核心線程空閑的的時候該線程就會被立即回收苹威,所以我們可以使用他來操作定時任務(wù)和重復(fù)的任務(wù)(和Task TimeTask 有些像)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); } /* * 獲取使用方法 */ Runnable r=new Runnable(){ @Override run(){ ..... } } ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); // 1000ms 后執(zhí)行任務(wù) executor.schedule(r,1000,TimeUnit.MICROSECONDS); // 延遲1000ms 每隔1000ms 重復(fù)執(zhí)行 任務(wù) executor.scheduleAtFixedRate(r,1000,1000,TimeUnit.MICROSECONDS)驾凶;
-
SingleThreadExector
- 創(chuàng)建方式為使用Executors的newCachedThreadPool()方法來創(chuàng)建牙甫,這種線程只有唯一一個核心線程掷酗,并且保證所有執(zhí)行的的任務(wù)都在這一個線程中執(zhí)行,并且是順序執(zhí)行窟哺,也就不用在考慮線程同步的問題了泻轰。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } /* * 獲取使用方法 */ ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(r); Runnable r=new Runnable(){ @Override run(){ ..... } } ExecutorService executor = Executors.newSingleThreadExecutor(); executor.execute(r)且轨;
-
-
通過上面對Java四種線程池的介紹,我們可以發(fā)現(xiàn)最終都是新建ThreadPoolExecutor對象浮声,也就是說ThreadPoolExecutor才是線程池的核心實現(xiàn)。
-
ThreadPoolExecutor 比較常用的一個構(gòu)造方法
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); } //參數(shù)含義 corePoolSize:默認情況下核心線程數(shù)會一直存在旋奢,不管是否處于閑置狀態(tài)泳挥, 但是如果線程池設(shè)置了核心線程數(shù),也就是ThreadPoolExecutor的allowCoreThreadTimeOut這個boolean 為true黄绩,如果核心線程數(shù)為零羡洁,則allowCoreThreadTimeOut的值為true,超時時間為keepAliveTime的值, 也就是CachedThreadPool線程池的所有線程都能夠回收的原因爽丹,他的核心線程數(shù)為零,也就是沒有核心線程 maximumPoolSize:最大線程數(shù) keepAliveTime:非核心線程超時時長筑煮,如果allowCoreThreadTimeOut的值為true, 則該超時時長也會作用于空閑狀態(tài)的核心線程 unit:超時時長的時間單位 TimeUnit.MILLISECONDS/SECONDS/MINUTES(毫秒/秒/分鐘) workQueue:線程任務(wù)隊列粤蝎,存放線程任務(wù) threadFactory:線程池線程生產(chǎn)工廠真仲,為線程池創(chuàng)建新線程 //我們看到構(gòu)造放中還有一個defaultHandler參數(shù),他其實是RejectedExecutionHandler對象 defaultHandler:當(dāng)線程隊列滿了初澎,或者線程任務(wù)無法執(zhí)行則用該參數(shù)拋出通知RejectedExecutionException秸应,這里構(gòu)造方法暫時沒用到
-
在Android中我們可以寫自己的線程管理類接,下面就來實現(xiàn)一個自己的線程池管理類來管理我們的線程
/** * Created by 毛麒添 on 2018/8/1 0010. * 線程管理類碑宴,線程池為單例 */ public class ThreadManager { private static ThreadPool mThreadPool; public static ThreadPool getmThreadPool(){ if (mThreadPool==null){ synchronized (ThreadManager.class){ if(mThreadPool==null){ //線程安全 mThreadPool=new ThreadPool(5,10,1L); } } } return mThreadPool; } //線程池 public static class ThreadPool{ private int corePoolSize;//核心線程數(shù) 5 private int maximumPoolSize;//最大線程數(shù) 10 private long keepAliveTime;//線程休眠時間 1秒 private ThreadPoolExecutor executor; private ThreadPool( int corePoolSize, int maximumPoolSize,long keepAliveTime){ this.corePoolSize=corePoolSize; this.maximumPoolSize=maximumPoolSize; this.keepAliveTime=keepAliveTime; } public void execute(Runnable runnable){ /** * int corePoolSize, 核心線程數(shù) * int maximumPoolSize, 最大線程數(shù) * long keepAliveTime, 線程休眠時間 * TimeUnit unit, 時間單位 * BlockingQueue<Runnable> workQueue, 線程隊列 * ThreadFactory threadFactory, 生成線程的工廠 */ if(executor==null){ executor = new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); } //核心線程也有超時機制 executor.allowCoreThreadTimeOut(true); executor.execute(runnable); } //取消任務(wù)软啼,從任務(wù)隊列中將其移除 public void cancelTask(Runnable runnable){ if(runnable!=null){ executor.getQueue().remove(runnable); } } } } //使用 ThreadManager.getmThreadPool().execute(new Runnable() { @Override public void run() { //執(zhí)行任務(wù) } });
-
好了,這就是我所了解的線程池知識延柠,如果有錯祸挪,請給我留言指出,大家一起學(xué)習(xí)進步贞间。
-
參考資料:
- 《Android開發(fā)藝術(shù)探索》
- 《Java編程思想》(第四版)
同步掘金地址