写于:2020-02-09
一、废弃的方法 Thread.stop :不推荐使用
java 官方文档提到该方法已经废弃,并提到废弃原因:通过该方法停止线程,线程可能不会释放被线程占用的所有锁。
二、线程生命周期正常结束
线程运行结束,就会正常退出,如果线程中的任务耗时比较短或者时间可控,直接放任其自行结束。
三、捕获中断信息关闭线程
通过捕获中断信号,结束线程,案例如下:
public class SimpleThread {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("准备开始执行任务");
while (!isInterrupted()){ // 该方法不会复位标志位
// todo
// 存在的问题:如果这里夯住了,即使发送了中断,也无法中断线程运行
}
System.out.println("任务执行结束");
}
};
thread.start();
TimeUnit.MILLISECONDS.sleep(10);
System.out.println("============任务即将结束");
thread.interrupt();
}
}
通过中断标识来进行线程是否关闭的控制。
该方式存在问题,如果在 while 循环的执行逻辑夯住了,此时线程便无法结束生命周期
四、通过 volatile 开关控制
代码案例如下:
public class SimpleThread {
public static void main(String[] args) throws InterruptedException {
MyTask thread = new MyTask();
thread.start();
TimeUnit.MILLISECONDS.sleep(10);
System.out.println("============任务即将结束");
thread.close();
}
public static class MyTask extends Thread{
// 开关
private volatile boolean closed = false;
@Override
public void run() {
System.out.println("准备开始执行任务");
while (!closed && !isInterrupted()){ // 该方法不会复位标志位
// todo
// 存在的问题:如果这里夯住了,即使发送了中断,也无法中断线程运行
}
System.out.println("任务执行结束");
}
public void close(){
this.closed = true;
this.interrupt();
}
}
}
该方式存在问题,如果在 while 循环的执行逻辑夯住了,此时线程便无法结束生命周期
五、通过守护线程的方式关闭线程:强制线程停止
public class SimpleThread {
public static void main(String[] args) throws InterruptedException {
ThreadService threadService = new ThreadService();
threadService.execute(()->{
//1-模拟任务被 夯住了
while (true){
}
});
TimeUnit.SECONDS.sleep(10);
// 通过结束executeThread 来实现强制中断任务线程
threadService.shutdown();
}
public static class ThreadService{
/** 执行线程 **/
private Thread executeThread;
/** 是否执行结束:true 是,false 否 **/
private boolean finished = false;
/** 执行逻辑 **/
public void execute(Runnable runnable){
executeThread = new Thread(){
@Override
public void run() {
Thread runner = new Thread(runnable);
runner.setDaemon(true); // 设置为守护线程,executerTHread 结束守护线程一起结束
runner.start();
try {
runner.join(); // 等待 runner 执行结束,才会执行 executerThread 线程逻辑
finished = true;
} catch (InterruptedException e) {
// 中断线程,使得守护线程一样跟着结束
e.printStackTrace();
}
}
};
executeThread.start();
}
/**
* 强制停止线程
*/
public void shutdown(){
while (!finished){
executeThread.interrupt();
break;
}
finished = true;
}
}
}
通过中断线程,使得守护线程也中断来达到强制中断任务线程的目的。