说明
默认情况下,如果空闲线程的存活时间,超过这个时间, 空闲线程被回收(但核心线程不会回收)
空闲线程
当线程的任务执行后,即:run() 方法里面的代码执行结束后,就是空闲线程
类比
学校规定,当教室没有人时,就是空闲教室,空闲超过1小时,就要关闭空调,否则就浪费电
该参数可能无意义
因为默认情况下,核心线程不会回收,所以:核心线程数量,等于 最大线程数量,那么这个参数无意义
例子
设置 线程池 核心线程数是 1,最大线程数是3,空闲线程最大存活时间 5s,阻塞队列长度 1
package ThreadPool;
import java.time.LocalTime;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class KeepAliveTime {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1,
3,
5,
TimeUnit.SECONDS,
new LinkedBlockingQueue(1)
);
// threadPoolExecutor.allowCoreThreadTimeOut(true);
threadPoolExecutor.execute(new MyRun("1"));
threadPoolExecutor.execute(new MyRun("2"));
threadPoolExecutor.execute(new MyRun("3"));
threadPoolExecutor.execute(new MyRun("4"));
for(;;){
print(threadPoolExecutor);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
static void print(ThreadPoolExecutor threadPoolExecutor){
LocalTime time = LocalTime.now();
System.out.println(" "+time+",活动线程数:"+threadPoolExecutor.getActiveCount());
System.out.println(" "+time+",线程池中的线程数:"+threadPoolExecutor.getPoolSize());
}
static class MyRun implements Runnable {
String name;
public MyRun(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println(name+"--开始");
try {
// for(int i =0;true;++i) {
// System.out.println(name+",i="+i);
// Thread.sleep(1000);
// }
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(name+"--结束");
}
}
}
执行结果:
执行步骤:
- 首先提交 任务1 ,立即创建线程 ,执行任务1;
- 提交 任务2 时,任务1还未完成,于是,将任务2,保存到 阻塞队列中
- 提交 任务3 ,此时 任务1 未完成,任务2 还在阻塞队列中等待,所以此时已经达到核心线程数,并且阻塞队列已经满了,但还没有达到最大线程数,因此,创建新线程执行任务3
- 任务4 提交,此时 任务1 未完成,任务2 还在阻塞队列中等待,任务3 也未完成,所以此时已经达到核心线程数,并且阻塞队列已经满了,但还没有达到最大线程数,因此,创建新线程执行任务4
- 此时 活动线程数是 3,线程池中的线程数:3
任务 1 执行完毕,队列中的任务 2开始执行。此时线程数还是 3
任务 3、任务4 相继执行完毕,因为
空闲线程最大存活时间 5s,所以,线程池中的线程不会回收。活动线程数:1(任务 2在运行),线程池中的线程数:3任务 3结束的 5s 后,线程池开始回收空闲线程,所以,活动线程数:0(任务 2 此时也执行完毕),线程池中的线程数:1,因为核心线程数是1,默认核心线程不会超时终止。
例子2
调用下面方法,可以回收核心线程
.allowCoreThreadTimeOut(true);
代码:
package ThreadPool;
import java.time.LocalTime;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class KeepAliveTime {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
1,
3,
5,
TimeUnit.SECONDS,
new LinkedBlockingQueue(1)
);
threadPoolExecutor.allowCoreThreadTimeOut(true);
threadPoolExecutor.execute(new MyRun(1));
threadPoolExecutor.execute(new MyRun(2));
threadPoolExecutor.execute(new MyRun(3));
threadPoolExecutor.execute(new MyRun(4));
for(;;){
print(threadPoolExecutor);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
static void print(ThreadPoolExecutor threadPoolExecutor){
LocalTime time = LocalTime.now();
System.out.println(" "+time+",活动线程数:"+threadPoolExecutor.getActiveCount());
System.out.println(" "+time+",线程池中的线程数:"+threadPoolExecutor.getPoolSize());
}
static class MyRun implements Runnable {
int index;
public MyRun(int name) {
this.index = name;
}
@Override
public void run() {
System.out.println(index +"--开始");
try {
// for(int i =0;true;++i) {
// System.out.println(name+",i="+i);
// Thread.sleep(1000);
// }
Thread.sleep(2000* index);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(index +"--结束");
}
}
}
执行最后结果:
线程池中的线程数:0 // 说明核心线程也回收了
参考:
https://blog.csdn.net/weixin_44730681/article/details/113791867
