实现思路--将任务线程设置为调用线程的守护线程,通过使调用线程中断来迫使任务线程中断
实现如下:
package org.currency.test03;
/**
* 优雅关闭线程--设置为守护线程
*
* @date 2020-07-30 08:43
**/
public class ThreadService {
private boolean isFinish = false;
private Thread taskThread;
private Thread currentThread;
/**
* @param task 任务线程
* @return
*/
public void execute(Runnable task) {
//当前线程
currentThread = new Thread(() -> {
//任务线程
taskThread = new Thread(task);
//将任务线程设置为当前线程的守护线程
taskThread.setDaemon(true);
//启动任务线程
taskThread.start();
try {
//任务线程执行完毕后再启用当前线程处理标志位
taskThread.join();
//任务线程执行完毕
isFinish = true;
} catch (InterruptedException e) {
//捕获到中断信号
System.out.println("中断退出");
}
});
//启动当前线程
currentThread.start();
}
/**
* 关闭线程(并指定最大执行时间)
*
* @param interruptTimes 线程执行最长时间
* @return 线程执行用时
* @throws InterruptedException
*/
public long shutDown(Long interruptTimes) throws InterruptedException {
//获取调用结束线程的当前时间
long begin = System.currentTimeMillis();
//如果任务线程没有执行完毕或未超时,等待
while (!isFinish) {
//如果超时,打断当前线程,当前线程的守护线程即任务线程被死亡(守护线程会随着主线程消亡而消亡)
if (System.currentTimeMillis() - interruptTimes >= begin) {
currentThread.interrupt();
break;
}
//未超时也未完成,睡眠避免资源消耗
Thread.sleep(1);
}
//任务线程执行完毕,中断当前线程
currentThread.interrupt();
long finish = System.currentTimeMillis();
return finish - begin;
}
}
掉用线程测试:
package org.currency.test03;
/**
* 中断线程测试
*
* @date 2020-07-30 09:23
**/
public class ThreadTest {
public static void main(String[] args) {
ThreadService thread =new ThreadService();
thread.execute(()->{
while (true){
}
});
try {
long useTimes = thread.shutDown(5000L);
System.out.println(useTimes);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果: