所有的現(xiàn)代操作系統(tǒng)都通過(guò)進(jìn)程和線程來(lái)支持并發(fā)。進(jìn)程是通常彼此獨(dú)立運(yùn)行的程序的實(shí)例,比如,如果你啟動(dòng)了一個(gè)Java程序,操作系統(tǒng)產(chǎn)生一個(gè)新的進(jìn)程,與其他程序一起并行執(zhí)行。在這些進(jìn)程的內(nèi)部,我們使用線程并發(fā)執(zhí)行代碼,因此,我們可以最大限度的利用CPU可用的核心(core)。Java從JDK1.0開(kāi)始執(zhí)行線程。在開(kāi)始一個(gè)新的線程之前,你必須指定由這個(gè)線程執(zhí)行的代碼,通常稱為task。這可以通過(guò)實(shí)現(xiàn)Runnable:
一個(gè)定義了一個(gè)無(wú)返回值無(wú)參數(shù)的run()
方法的函數(shù)接口,如下面的代碼所示:
Runnable task = () -> { //JDK 1.8中的Lambda 表達(dá)式 String threadName = Thread.currentThread().getName(); System.out.2. java 線程池的使用
上面繼承Thread類(lèi)和實(shí)現(xiàn)Runnable接口,可以實(shí)現(xiàn)多線程。但是如果并發(fā)的線程數(shù)量很多,并且每個(gè)線程都是執(zhí)行一個(gè)時(shí)間很短的任務(wù)就結(jié)束了,這樣頻繁創(chuàng)建線程就會(huì)大大降低系統(tǒng)的效率,因?yàn)轭l繁創(chuàng)建線程和銷(xiāo)毀線程需要時(shí)間。那么有沒(méi)有一種辦法使得線程可以復(fù)用,就是執(zhí)行完一個(gè)任務(wù),并不被銷(xiāo)毀,而是可以繼續(xù)執(zhí)行其他的任務(wù)?在Java中可以通過(guò)線程池來(lái)達(dá)到這樣的效果。今天我們就來(lái)詳細(xì)講解一下Java的線程池,首先我們從最核心的ThreadPoolExecutor類(lèi)中的方法講起,然后再講述它的實(shí)現(xiàn)原理,接著給出了它的使用示例,最后討論了一下如何合理配置線程池的大小。
Java中的ThreadPoolExecutor類(lèi),java..uitl.concurrent.ThreadPoolExecutor類(lèi)是線程池中最核心的一個(gè)類(lèi),因此如果要透徹地了解Java中的線程池,必須先了解這個(gè)類(lèi)。下面我們來(lái)看一下ThreadPoolExecutor類(lèi)的具體實(shí)現(xiàn)源碼。
public class ThreadPoolExecutor extends AbstractExecutorService { public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler); }從上面的代碼可以得知,ThreadPoolExecutor繼承了AbstractExecutorService類(lèi),并提供了四個(gè)構(gòu)造器,事實(shí)上,通過(guò)觀察每個(gè)構(gòu)造器的源碼具體實(shí)現(xiàn),發(fā)現(xiàn)前面三個(gè)構(gòu)造器都是調(diào)用的第四個(gè)構(gòu)造器進(jìn)行的初始化工作。下面解釋下一下構(gòu)造器中各個(gè)參數(shù)的含義:
coorPoolSize:核心池的大小,這個(gè)參數(shù)跟后面講述的線程池的實(shí)現(xiàn)原理有非常大的關(guān)系。在創(chuàng)建了線程池后,默認(rèn)情況下,線程池中并沒(méi)有任何線程,而是等待有任務(wù)到來(lái)才創(chuàng)建線程去執(zhí)行任務(wù),除非調(diào)用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個(gè)方法的名字就可以看出,是預(yù)創(chuàng)建線程的意思,即在沒(méi)有任務(wù)到來(lái)之前就創(chuàng)建corePoolSize個(gè)線程或者一個(gè)線程。默認(rèn)情況下,在創(chuàng)建了線程池后,線程池中的線程數(shù)為0,當(dāng)有任務(wù)來(lái)之后,就會(huì)創(chuàng)建一個(gè)線程去執(zhí)行任務(wù),當(dāng)線程池中的線程數(shù)目達(dá)到corePoolSize后,就會(huì)把到達(dá)的任務(wù)放到緩存隊(duì)列當(dāng)中;maximumPoolSize:線程池最大線程數(shù),這個(gè)參數(shù)也是一個(gè)非常重要的參數(shù),它表示在線程池中最多能創(chuàng)建多少個(gè)線程;keepAliveTime:表示線程沒(méi)有任務(wù)執(zhí)行時(shí)最多保持多久時(shí)間會(huì)終止。默認(rèn)情況下,只有當(dāng)線程池中的線程數(shù)大于corePoolSize時(shí),keepAliveTime才會(huì)起作用,直到線程池中的線程數(shù)不大于corePoolSize,即當(dāng)線程池中的線程數(shù)大于corePoolSize時(shí),如果一個(gè)線程空閑的時(shí)間達(dá)到keepAliveTime,則會(huì)終止,直到線程池中的線程數(shù)不超過(guò)corePoolSize。但是如果調(diào)用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數(shù)不大于corePoolSize時(shí),keepAliveTime參數(shù)也會(huì)起作用,直到線程池中的線程數(shù)為0;unit參數(shù):keepAliveTime的時(shí)間單位,有7種取值,在TimeUnit類(lèi)中有7種靜態(tài)屬性:
TimeUnit.DAYS; //天TimeUnit.HOURS; //小時(shí)TimeUnit.MINUTES; //分鐘TimeUnit.SECONDS; //秒TimeUnit.MILLISECONDS; //毫秒TimeUnit.MICROSECONDS; //微妙TimeUnit.NANOSECONDS; //納秒workQueue:一個(gè)阻塞隊(duì)列,用來(lái)存儲(chǔ)等待執(zhí)行的任務(wù),這個(gè)參數(shù)的選擇也很重要,會(huì)對(duì)線程池的運(yùn)行過(guò)程產(chǎn)生重大影響,一般來(lái)說(shuō),這里的阻塞隊(duì)列有以下幾種選擇:
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注