Categories
程式開發

Java-技術專題-多線程之線程池


一、線程池的構造

使用線程池離不開ThreadPoolExecutor類,該類實現了ExecutorService接口,其構造方法如下:

public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);1

參數說明如下:

corePoolSize:核心池大小

maximumPoolSize:線程池大小(maximumPoolSize >= corePoolSize)

keepAliveTime:沒有任務時線程的存活時間,默認情況下只有線程數目大於corePoolSize時,此參數才起作用,若線程數目等於corePoolSize,則這些線程會一直存活。但若調用allowCoreThreadTimeOut(boolean)方法,則線程數目不大於corePoolSize時,此參數也起作用,直到線程數目為0

unit:keepAliveTime的時間單位,有以下七種取值:

TimeUnit.DAYS;//天TimeUnit.HOURS;//小時TimeUnit.MINUTES;//分鐘TimeUnit.SECONDS;//秒TimeUnit.MILLISECONDS;//毫秒TimeUnit.MICROSECONDS;//微秒TimeUnit.NANOSECONDS;//納秒

workQueue:指定構成緩衝區的阻塞隊列,即指定了線程池的排隊策略,常用的有以下三種:

ArrayBlockingQueue:基於數組的先進先出隊列,此隊列創建時必須指定大小LinkedBlockingQueue:基於鍊錶的先進先出隊列,如果創建時沒有指定此隊列大小,則默認為Integer.MAX_VALUEsynchronousQueue:這個隊列不會保存提交的任務,而是將直接新建一個線程來執行新來的任務

threadFactory(可選):線程工廠,用來創建線程,可自定義

handler(可選):拒絕策略,有以下四種策略可選:

ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。 ThreadPoolExecutor.DiscardPolicy:丟棄任務,不拋出異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然後重新嘗試執行任務ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務

二、線程池的運行過程

如果當前線程池中的線程數目小於corePoolSize,則每來一個任務,就會創建一個線程去執行這個任務如果當前線程池中的線程數目>=corePoolSize,則每來一個任務,會嘗試將其添加到任務緩存隊列當中,若添加成功,則該任務會等待空閒線程將其取出去執行;若添加失敗(一般來說是任務緩存隊列已滿),則會嘗試創建新的線程去執行這個任務

如果當前線程池中的線程數目達到maximumPoolSize,則會採取任務拒絕策略進行處理

如果線程池中的線程數量大於corePoolSize時,如果某線程空閒時間超過keepAliveTime,線程將被終止,直至線程池中的線程數目不大於corePoolSize;

如果允許為核心池中的線程設置存活時間(調用allowCoreThreadTimeOut(boolean)方法),那麼核心池中的線程空閒時間超過keepAliveTime,線程也會被終止

三、線程的初始化

默認情況下,線程池構造完成後是沒有線程的,需要等任務提交時才會創建線程,如果需要在線程池構造完成時就創建線程,可以調用以下兩個方法:

prestartCoreThread():初始化一個核心線程;

prestartAllCoreThreads():初始化所有核心線程

四、線程池的關閉

shutdown():不會立即關閉線程池,而是不再接受新的任務,等當前所有任務處理完之後關閉線程池

shutdownNow():立即關閉線程池,打斷正在執行的任務,清空緩衝隊列,返回尚未執行的任務

五、任務提交

任務提交有兩種方法,execute()和submit()

void execute(Runnable task),無返回值

Futuresubmit(可運行任務,T結果)/ Futuresubmit(可調用任務),有返回值

六、可選線程池模型(Executors類的靜態工廠方法)

newCachedThreadPool():ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue())newFixedThreadPool(int nThreads):ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue()new 1,1,0L,TimeUnit.MILLISECONDS,新的LinkedBlockingQueue())newScheduledThreadPool(int nThreads):ScheduledThreadPoolExecutor(nThreads,Integer.MAX_VALUE,0L,TimeUnit.NANOSECONDS,new DelayedWorkQueue())newSingleScheduledThreadPool():newScheduledThreadPool :ExecutorService池= Executors.newCachedThreadPool();

構造線程池時優先選用線程池模型,如果這些模型不能滿足要求,再自定義ThreadPoolExecutor線程池