测试下面代码,得出结论:
1.线程通过异常导致退出的,将不会被自动重启,当来新任务的时候,不会处理。
2.线程通过在设定时间内未得到使用 (就是空闲线程的存活时间)的线程,当有新任务来的时候,会启动线程来处理。
原因:
- Java 的线程池(如
ThreadPoolExecutor
)并不会对由于异常退出的线程进行自动重启。 - 异常退出的线程会从线程池中移除,线程池中的线程数量(
getPoolSize
)会减少。 - 如果线程池中还有剩余的活跃线程,这些线程会继续处理新任务,但 因异常退出的线程不会自动恢复。
import java.util.concurrent.*;
public class ThreadPoolExceptionTest {
public static void main(String[] args) {
// 创建一个线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
3, // 核心线程数
5, // 最大线程数
60L, TimeUnit.SECONDS, // 空闲线程的存活时间
new LinkedBlockingQueue<>(), // 任务队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
// 定时任务:每隔5秒打印一次线程池状态
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
System.out.println("当前线程池活跃线程数:" + threadPool.getActiveCount());
System.out.println("当前线程池任务队列长度:" + threadPool.getQueue().size());
System.out.println("当前线程池已完成任务数:" + threadPool.getCompletedTaskCount());
System.out.println("当前线程池总任务数:" + threadPool.getTaskCount());
}, 0, 5, TimeUnit.SECONDS);
// 提交初始任务
for (int i = 0; i < 5; i++) {
threadPool.submit(new RestartableTask(i, threadPool));
}
// 关闭线程池
threadPool.shutdown();
monitor.shutdown();
}
/**
* 一个任务类,模拟任务执行过程中发生异常。
*/
static class RestartableTask implements Runnable {
private final int taskId;
private final ThreadPoolExecutor threadPool;
public RestartableTask(int taskId, ThreadPoolExecutor threadPool) {
this.taskId = taskId;
this.threadPool = threadPool;
}
@Override
public void run() {
try {
System.out.println("线程 " + Thread.currentThread().getName() + " 开始处理任务 " + taskId);
if (Math.random() < 0.5) { // 模拟任务执行中随机发生异常
throw new RuntimeException("模拟异常!");
}
// 模拟任务耗时
Thread.sleep(2000);
System.out.println("线程 " + Thread.currentThread().getName() + " 完成任务 " + taskId);
} catch (Exception e) {
System.err.println("线程 " + Thread.currentThread().getName() + " 任务 " + taskId + " 发生异常:" + e.getMessage());
// 重启任务
System.out.println("任务 " + taskId + " 将被重新提交!");
threadPool.submit(new RestartableTask(taskId, threadPool)); // 使用原线程池重新提交任务
}
}
}
}