Thread中断Interrupt方法学习&采用优雅的方式结束线程生命周期
Thread中断Interrupt方法学习&采用优雅的方式结束线程生命周期
在jdk中关于interrupt相关方法有三个:

简单来使用一下interrupt:
/**
* @program: ThreadDemo
* @description: 线程中断
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadInterrupt {
public static void main(String[] args) {
Thread t1 = new Thread("t1") {
@Override
public void run() {
while (true) {
}
}
};
t1.start();
// start之后处于runnable,并不一定马上就会running。所以设置短暂休眠等待t1启动
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t1.isInterrupted());
t1.interrupt();
System.out.println(t1.isInterrupted());
}
}
运行效果如下:

可以看到:没有中断的线程中断了,但是程序却没有结束。interrupt()不能中断在运行中的线程,它只能改变中断状态而已。
找到interrupt()方法的文档:

可以看到如果线程中调用wait,join,sleep会捕获InterruptedException:
我们先用sleep()方法试一下,代码如下:
/**
* @program: ThreadDemo
* @description: 线程中断
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadInterrupt {
public static void main(String[] args) {
Thread t1 = new Thread("t1") {
@Override
public void run() {
while (true) {
try {
Thread.sleep(3_1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.start();
// start之后处于runnable,并不一定马上就会running。所以设置短暂休眠等待t1启动
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t1.isInterrupted());
t1.interrupt();
System.out.println(t1.isInterrupted());
}
}

再试一下wait()方法:
/**
* @program: ThreadDemo
* @description: 线程中断
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadInterrupt {
private static final Object MONITOR = new Object();
public static void main(String[] args) {
Thread t1 = new Thread("t1") {
@Override
public void run() {
while (true) {
synchronized (MONITOR) {
try {
MONITOR.wait(1_000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
};
t1.start();
// start之后处于runnable,并不一定马上就会running。所以设置短暂休眠等待t1启动
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(t1.isInterrupted());
t1.interrupt();
System.out.println(t1.isInterrupted());
}
}
运行效果如下:

再试一下join():
/**
* @program: ThreadDemo
* @description: join中断线程
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadInterrupt {
private static final Object MONITOR = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
}
}, "t1");
t1.start();
Thread t2 = new Thread(() -> {
try {
Thread.sleep(100);
t1.interrupt();
System.out.println("interrupt t1 thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行效果如下:

线程t1被中断了,但是为什么没收到中断异常呢?
其实join()的是main线程,而我们打断的是t1线程,主线程的join()不会收到中断异常,所以代码改造如下:
/**
* @program: ThreadDemo
* @description: join中断线程
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadInterrupt {
private static final Object MONITOR = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
}
}, "t1");
t1.start();
Thread main = Thread.currentThread();
Thread t2 = new Thread(() -> {
try {
Thread.sleep(100);
main.interrupt();
System.out.println("interrupt t1 thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行效果如下:

同样也捕获到了中断异常,但都没有让t线程退出,我们来看一下join的源码:

其实join里也是用到了wait()方法的。
那么怎么能让t1线程退出呢,这里有个简单粗暴的方法,但是官方并不推荐,就是stop()方法:
我们在代码的结尾加上
t1.stop();
运行效果如下:

已经实现了我们想要的效果,但是并不推荐这么用,那么到底该怎么优雅的中断线程呢?
用一个标记来控制
/**
* @program: ThreadDemo
* @description: 优雅地停止线程 Graceful thread stop 1. 使用开关变量控制是否启动
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadCloseGraceful {
private static class Worker extends Thread {
private volatile boolean start = true;
@Override
public void run() {
while (start) {
// ...
}
}
public void shutdown() {
this.start = false;
}
}
public static void main(String[] args) throws InterruptedException {
Worker worker = new Worker();
worker.start();
Thread.sleep(2_000);
worker.shutdown();
}
}
运行效果如下:

利用打断机制
/**
* @program: ThreadDemo
* @description: 优雅地停止线程 Graceful thread stop 通过打断的方式实现
* @author: hs96.cn@Gmail.com
* @create: 2020-09-03
*/
public class ThreadCloseGraceful2 {
private static class Worker extends Thread {
@Override
public void run() {
while (true) {
// 1. sleep()
/*try {
Thread.sleep(1);
} catch (InterruptedException e) {
break;// return;
}*/
// 2. if
if (Thread.interrupted()) {
break;// return;
}
}
// ... catch中使用break;可以在while()后执行其他操作
System.out.println("break-opera after while");
}
}
public static void main(String[] args) throws InterruptedException {
Worker worker = new Worker();
worker.start();
Thread.sleep(3_000);
worker.interrupt();
}
}
运行效果如下:

上面两个方法确实可以中断线程,但是有这样一个问题改如何解决呢?

也就是除了第一次判断了一下interrupted,后面就被阻塞了,那么改如何解决呢?这个我们后续再学习。

浙公网安备 33010602011771号