如何优雅终止线程
分为两个阶段终止线程
1、interrupted()
: 让线程从休眠状态转换到RUNNABLE 状态
2、线程终止的标志位
:线程会在合适的时机检查这个标志位,如果发现符合终止条件,则自动退出 run() 方法
public class MonitorThread extends Thread {
//在监控线程中添加一个volatile类型的标志变量,用于标识是否需要终止线程的执行
private volatile boolean terminated = false;
public void run() {
while (!terminated) {
// 执行监控操作
System.out.println("监控线程正在执行监控操作...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 执行清理操作
System.out.println("监控线程正在执行清理操作...");
releaseResources();
}
public void terminate() {
//设置标志变量为true,并等待一段时间
terminated = true;
try {
join(5000); // 等待5秒钟,期间监控线程会检查terminated的状态
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void releaseResources() {
// 释放资源和进行必要的清理工作
System.out.println("监控线程正在释放资源和进行必要的清理工作...");
}
public static void main(String[] args) throws InterruptedException {
MonitorThread thread = new MonitorThread();
//启动监控线程
thread.start();
//主线程休眠期间,监控线程在执行监控操作
Thread.sleep(10000);
//终止监控线程
thread.terminate();
Thread.sleep(100000);
}
}
如何优雅终止线程池
线程池有两个终止线程池API:shutdownNow()、shotdown()
1、shotdown
:会停止线程池接受新的任务,并等待线程池中的所有任务执行完毕
,然后关闭线程池。。在调用shutdown()方法后,线程池不再接受新的任务,但是会将任务队列中的任务继续执行直到队列为空。如果线程池中的任务正在执行,但是还没有执行完毕,线程池会等待所有任务执行完毕后再关闭线程池。
2、shutdownNow
:会停止线程池接受新的任务,并尝试中断正在执行任务的线程,然后关闭线程池。在调用shutdownNow()方法后,线程池不再接受新的任务,同时会中断正在执行任务的线程并返回一个未执行的任务列表
3、awaitTerminal
等待线程池中的任务执行完毕,或者超时时间到达
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.submit(() -> {
try {
// 执行任务操作
System.out.println(Thread.currentThread().getName() + "正在执行任务...");
Thread.sleep(5000);
} catch (InterruptedException e) {
// 重新设置中断状态
Thread.currentThread().interrupt();
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "任务执行完毕");
}
});
}
// 停止线程池接受新的任务,但不能强制停止已经提交的任务
executorService.shutdown();
// 等待线程池中的任务执行完毕,或者超时时间到达
boolean terminated = executorService.awaitTermination(3, TimeUnit.SECONDS);
if (!terminated) {
// 如果线程池中还有未执行完毕的任务,则调用线程池的shutdownNow方法,中断所有正在执行的任务
// 如果有还没开始执行的任务,则返回未执行的任务列表
List<Runnable> tasks = executorService.shutdownNow();
System.out.println("剩余未执行的任务数:" + tasks.size());
}
}