java线程池keepAliveTime的含义说明
之前对线程池中属性:keepAliveTime⽐较模糊,⽽且看过之后过⼀段时间就会忘掉,于是就在此记录⼀下。keepAliveTime的jdk中的解释为:
当线程数⼤于核⼼时,此为终⽌前多余的空闲线程等待新任务的最长时间。
说的让⼈感觉⽐较模糊,总结⼀下⼤概意思为:⽐如说线程池中最⼤的线程数为50,⽽其中只有40个线程任务在跑,相当于有10个空闲线程,这10个空闲线程不能让他⼀直在开着,因为线程的存在也会特别好资源的,所有就需要设置⼀个这个空闲线程的存活时间,这么解释应该就很清楚了。
这样以后忘记了就过来看看就OK了。
补充:线程池的状态及KeepAliveTime参数
五个状态
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
循环getTask⽅法
/**
* Performs blocking or timed wait for a task, depending on
* current configuration settings, or returns null if this worker
* must exit because of any of:
* 1. There are more than maximumPoolSize workers (due to
* a call to setMaximumPoolSize).
* 2. The pool is stopped.
* 3. The pool is shutdown and the queue is empty.
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
retry是什么意思* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* both before and after the timed wait.
*
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
*/
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
retry:
for (;;) {
int c = ();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
boolean timed; // Are workers subject to culling?
for (;;) {
int wc = 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))
return null;
c = (); // Re-rea
d ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
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的时候,就return null,就会跳出循环,回收线程。
if (wc <= maximumPoolSize && ! (timedOut && timed))
break;
if (compareAndDecrementWorkerCount(c))
return null;
allowCoreThreadTimeout : 默认情况下核⼼线程不会退出,可通过将该参数设置为true,让核⼼线程也退出。
默认的Executors⼯⼚,只有newCachedThreadPool,timeout为60秒,出现timeout情况下,⽽且线程数超过了核⼼线程数,会销毁销毁线程。保持在corePoolSize数(如果是cached的,corePoolSize为0)。
/**
* Timeout in nanoseconds for idle threads waiting for work.
* Threads use this timeout when there are more than corePoolSize
* present or if allowCoreThreadTimeOut. Otherwise they wait
* forever for new work.
*/
private volatile long keepAliveTime;
/**
* If false (default), core threads stay alive even when idle.
* If true, core threads use keepAliveTime to time out waiting
* for work.
*/
private volatile boolean allowCoreThreadTimeOut;
线程池最⼩是corePoolSize,最⼤是maximumPoolSize,除⾮设置了allowCoreThreadTimeOut和超时时间,这种情况线程数可能减少到0,最⼤可能是Integer.MAX_VALUE。
Core pool size is the minimum number of workers to keep alive(and not allow to time out etc) unless
allowCoreThreadTimeOut is set, in which case the minimum is zero.
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to <tt>execute</tt> will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available, and uses the provided
* ThreadFactory to create new threads when needed.
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
超时timeout设置为0的话,表⽰不等待
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
return pollFirst(timeout, unit);
}
具体如下
public E pollFirst(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = Nanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
E x;
while ( (x = unlinkFirst()) == null) {
if (nanos <= 0)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
return x;
} finally {
lock.unlock();
}
}
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论