java 线程池keepAliveTime的含义说明
之前对线程池中属性:keepAliveTime比较模糊,而且看过之后过一段时间就会忘掉,于是就在此记录一下。
keepAliveTime的jdk中的解释为:
当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。
说的让人感觉比较模糊,总结一下大概意思为:比如说线程池中最大的线程数为50,而其中只有40个线程任务在跑,相当于有10个空闲线程,这10个空闲线程不能让他一直在开着,因为线程的存在也会特别好资源的,所有就需要设置一个这个空闲线程的存活时间,这么解释应该就很清楚了。
这样以后忘记了就过来看看就OK了。
补充:线程池的状态及KeepAliveTime参数
五个状态
//runStateisstoredinthehigh-orderbits privatestaticfinalintRUNNING=-1<循环getTask方法
/** *Performsblockingortimedwaitforatask,dependingon *currentconfigurationsettings,orreturnsnullifthisworker *mustexitbecauseofanyof: *1.TherearemorethanmaximumPoolSizeworkers(dueto *acalltosetMaximumPoolSize). *2.Thepoolisstopped. *3.Thepoolisshutdownandthequeueisempty. *4.Thisworkertimedoutwaitingforatask,andtimed-out *workersaresubjecttotermination(thatis, *{@codeallowCoreThreadTimeOut||workerCount>corePoolSize}) *bothbeforeandafterthetimedwait. * *@returntask,ornulliftheworkermustexit,inwhichcase *workerCountisdecremented */ privateRunnablegetTask(){ booleantimedOut=false;//Didthelastpoll()timeout? retry: for(;;){ intc=ctl.get(); intrs=runStateOf(c); //Checkifqueueemptyonlyifnecessary. if(rs>=SHUTDOWN&&(rs>=STOP||workQueue.isEmpty())){ decrementWorkerCount(); returnnull; } booleantimed;//Areworkerssubjecttoculling? for(;;){ intwc=workerCountOf(c); timed=allowCoreThreadTimeOut||wc>corePoolSize; //默认allowCoreThreadTimeOut为false,除非程序指定 //(1)当没有超过核心线程时,默认allowCoreThreadTimeOut为false时 //timed值为false,始终break掉,不会销毁线程 //(2)当超过核心线程数,默认allowCoreThreadTimeOut为false时 //timed值为true,如果超过最大值,则销毁;如果timeout过,则销毁 //如果allowCoreThreadTimeOut为true,则timed始终为true if(wc<=maximumPoolSize&&!(timedOut&&timed)) break; if(compareAndDecrementWorkerCount(c)) returnnull; c=ctl.get();//Re-readctl if(runStateOf(c)!=rs) continueretry; //elseCASfailedduetoworkerCountchange;retryinnerloop } try{ Runnabler=timed? workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS): workQueue.take(); if(r!=null) returnr; timedOut=true; }catch(InterruptedExceptionretry){ timedOut=false; } } }线程池状态大于SHUTDOWN值的两种情况
1、调用shutdown方法
当线程池调用了shutdown方法,线程池的状态会首先被设置为SHUTDOWN,然后遍历线程池中所有线程,调用一次interrupt方法,如果在休眠中的线程将会激活,激活后的线程以及调用shutdown方法本身的线程都会尝试去调用tryTerminate方法,该方法将判定如果线程池中所有记录的线程数为0,则将线程状态改为TERMINATED,这个值为3,将大于SHUTDOWN状态值。
2、调用shutdownNow方法
当线程调用了shutdownNow方法后,首先将线程的状态修改为STOP,这个状态是大于SHUTDOWN值的,接下来它也会通过中断激活线程,只是它来的更暴力一些,连加锁和一些基本判断都没有,直接中断;在调用tryTerminate之前会先清空阻塞队列中所有的元素,这些元素被组装为一个List列表作为shutdownNow方法的返回值。换句话说,没有执行的任务在shutdownNow执行后的返回值中可以得到。在程序某些必要的情况下,可以通过线程池的isTerminating,isTerminated,isStopped,isShutdown来对线程做一些状态判定。
KeepAliveTime参数
workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS)当阻塞队列中没有任务时,等待时间达到keepAliveTime毫秒值时就会被自动唤醒,而不会永远地沉睡下去。
keepAliveTime,如果是通过newCachedThreadPool的话,默认是1分钟超时,如果遇到前面所提到的瞬间冲击,那么线程池数量将瞬间快速膨胀,而且这些瞬间膨胀的线程的生命周期最少在1分钟以上。
如果设置了该参数,那么当timeout的时候,就returnnull,就会跳出循环,回收线程。
if(wc<=maximumPoolSize&&!(timedOut&&timed)) break; if(compareAndDecrementWorkerCount(c)) returnnull;allowCoreThreadTimeout:默认情况下核心线程不会退出,可通过将该参数设置为true,让核心线程也退出。
默认的Executors工厂,只有newCachedThreadPool,timeout为60秒,出现timeout情况下,而且线程数超过了核心线程数,会销毁销毁线程。保持在corePoolSize数(如果是cached的,corePoolSize为0)。
/** *Timeoutinnanosecondsforidlethreadswaitingforwork. *ThreadsusethistimeoutwhentherearemorethancorePoolSize *presentorifallowCoreThreadTimeOut.Otherwisetheywait *foreverfornewwork. */ privatevolatilelongkeepAliveTime; /** *Iffalse(default),corethreadsstayaliveevenwhenidle. *Iftrue,corethreadsusekeepAliveTimetotimeoutwaiting *forwork. */ privatevolatilebooleanallowCoreThreadTimeOut;线程池最小是corePoolSize,最大是maximumPoolSize,除非设置了allowCoreThreadTimeOut和超时时间,这种情况线程数可能减少到0,最大可能是Integer.MAX_VALUE。
Corepoolsizeistheminimumnumberofworkerstokeepalive(andnotallowtotimeoutetc)unlessallowCoreThreadTimeOutisset,inwhichcasetheminimumiszero.
/** *Createsathreadpoolthatcreatesnewthreadsasneeded,but *willreusepreviouslyconstructedthreadswhentheyare *available.Thesepoolswilltypicallyimprovetheperformance *ofprogramsthatexecutemanyshort-livedasynchronoustasks. *Callstoexecutewillreusepreviouslyconstructed *threadsifavailable.Ifnoexistingthreadisavailable,anew *threadwillbecreatedandaddedtothepool.Threadsthathave *notbeenusedforsixtysecondsareterminatedandremovedfrom *thecache.Thus,apoolthatremainsidleforlongenoughwill *notconsumeanyresources.Notethatpoolswithsimilar *propertiesbutdifferentdetails(forexample,timeoutparameters) *maybecreatedusing{@linkThreadPoolExecutor}constructors. * *@returnthenewlycreatedthreadpool */ publicstaticExecutorServicenewCachedThreadPool(){ returnnewThreadPoolExecutor(0,Integer.MAX_VALUE, 60L,TimeUnit.SECONDS, newSynchronousQueue()); } /** *Createsathreadpoolthatcreatesnewthreadsasneeded,but *willreusepreviouslyconstructedthreadswhentheyare *available,andusestheprovided *ThreadFactorytocreatenewthreadswhenneeded. *@paramthreadFactorythefactorytousewhencreatingnewthreads *@returnthenewlycreatedthreadpool *@throwsNullPointerExceptionifthreadFactoryisnull */ publicstaticExecutorServicenewCachedThreadPool(ThreadFactorythreadFactory){ returnnewThreadPoolExecutor(0,Integer.MAX_VALUE, 60L,TimeUnit.SECONDS, newSynchronousQueue (), threadFactory); } 超时timeout设置为0的话,表示不等待
publicEpoll(longtimeout,TimeUnitunit)throwsInterruptedException{ returnpollFirst(timeout,unit); }具体如下
publicEpollFirst(longtimeout,TimeUnitunit) throwsInterruptedException{ longnanos=unit.toNanos(timeout); finalReentrantLocklock=this.lock; lock.lockInterruptibly(); try{ Ex; while((x=unlinkFirst())==null){ if(nanos<=0) returnnull; nanos=notEmpty.awaitNanos(nanos); } returnx; }finally{ lock.unlock(); } }以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。