/*** 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;
等待工作的空闲线程的超时(以纳秒为单位)。
当存在超过 corePoolSize(即非核心线程) 或 allowCoreThreadTimeOut 为 true 时,线程使用此参数作为定时。
否则,他们会永远等待新的工作。
/*** 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;
如果为 false(默认值),则核心线程即使在空闲时也保持活动状态。
如果为 true,核心线程使用 keepAliveTime 定时等待工作。
/*** Sets the policy governing whether core threads may time out and* terminate if no tasks arrive within the keep-alive time, being* replaced if needed when new tasks arrive. When false, core* threads are never terminated due to lack of incoming* tasks. When true, the same keep-alive policy applying to* non-core threads applies also to core threads. To avoid* continual thread replacement, the keep-alive time must be* greater than zero when setting {@code true}. This method* should in general be called before the pool is actively used.** @param value {@code true} if should time out, else {@code false}* @throws IllegalArgumentException if value is {@code true}* and the current keep-alive time is not greater than zero** @since 1.6*/
public void allowCoreThreadTimeOut(boolean value) {if (value && keepAliveTime <= 0)throw new IllegalArgumentException("Core threads must have nonzero keep alive times");if (value != allowCoreThreadTimeOut) {allowCoreThreadTimeOut = value;if (value)interruptIdleWorkers();}
}
从注释得知
当设置为 false,核心线程在缺少任务执行的情况下也不终止。
当设置为 true,核心线程的存活策略适用于非核心线程。
防止线程持续替换,当设置 allowCoreThreadTimeOut 为 true 时 keepAliveTime 必须大于0.
传入的参数值与 allowCoreThreadTimeOut 的默认值不同时,先将 allowCoreThreadTimeOut 进行赋值为 true(默认值为 false),再终止线程。
从如下链接得知
https://www.zhihu.com/question/322212282/answer/667964027
1、keepAliveTime的存在的意义在于可以减少过于频繁的线程启动停止带来的性能消耗。
2、keepAliveTime的建议值在任何书籍、文档中都没有提到过。如果真的有建议值的话,我相信JDK会封装常量类。
3、keepAliveTime的值要视具体业务场景对待,如果这个线程池用在主业务逻辑上我觉得这个值设置为0也OK,如果这个线程池用在一个服务中且这个服务是单独一台机器部署的我觉得设置0也任然OK,如果这个线程池要执行的任务是非常密集型的我觉得这是0也同样OK。业务类型、业务权重、实施部署条件以及没一个具体的线程大概执行时间等都要考虑。
4、我见到过keepAliveTime设置为0,在线程体中根据条件来休眠线程的,我觉得这种方式也不错
这个看应用场景的,JDK自带的两种线程池构造:
newFixedThreadPool-0ms,固定大小的永不过期
newCachedThreadPool-60s,缓存大小的60秒过期
核心线程和非核心都用到这个变量值。设置回收核心线程时,这个值需要大于0。
考虑到实际情况,如果是普通任务后台执行时间很长的话,可以设置时长为1小时,1小时的时间是我接触过的很长的任务了,我做的一个项目通过定时任务后台执行就用了起码10分钟以上,好处是这个对时间要求不敏感,是夜里执行的任务。普通的web请求的话设置为1分钟即可。这样可以照顾到核心线程回收 keepAliveTime 设置的值需要大于0 的问题。
设置 allowCoreThreadTimeOut 为 true ,keepAliveTime 设置的值需要大于0。
/*** Returns the approximate number of threads that are actively* executing tasks.** @return the number of threads*/
public int getActiveCount() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {int n = 0;for (Worker w : workers)if (w.isLocked())++n;return n;} finally {mainLock.unlock();}
}
/*** Returns the approximate total number of tasks that have ever been* scheduled for execution. Because the states of tasks and* threads may change dynamically during computation, the returned* value is only an approximation.** @return the number of tasks*/
public long getTaskCount() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {long n = completedTaskCount;for (Worker w : workers) {n += w.completedTasks;if (w.isLocked())++n;}return n + workQueue.size();} finally {mainLock.unlock();}
}
/*** Returns the approximate total number of tasks that have* completed execution. Because the states of tasks and threads* may change dynamically during computation, the returned value* is only an approximation, but one that does not ever decrease* across successive calls.** @return the number of tasks*/
public long getCompletedTaskCount() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {long n = completedTaskCount;for (Worker w : workers)n += w.completedTasks;return n;} finally {mainLock.unlock();}
}
发现用到了全局变量 completedTaskCount
/*** Counter for completed tasks. Updated only on termination of* worker threads. Accessed only under mainLock.*/
private long completedTaskCount;
由注释得知,是历史任务结束后的数量统计。
可以得知,想要知道当前任务有多少线程在执行,通过 getActiveCount() 可以得到。
/*** Returns the task queue used by this executor. Access to the* task queue is intended primarily for debugging and monitoring.* This queue may be in active use. Retrieving the task queue* does not prevent queued tasks from executing.** @return the task queue*/
public BlockingQueue getQueue() {return workQueue;
}
/*** Returns the current number of threads in the pool.** @return the number of threads*/
public int getPoolSize() {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {// Remove rare and surprising possibility of// isTerminated() && getPoolSize() > 0return runStateAtLeast(ctl.get(), TIDYING) ? 0: workers.size();} finally {mainLock.unlock();}
}