🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在jdk中关于interrupt相关方法有三个: ![](https://img.kancloud.cn/d1/fb/d1fba3536dd5624e911c11afd16cf002_1070x278.png) 简单来使用一下interrupt: ```java /** * @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()); } } ``` 运行效果如下: ![](https://img.kancloud.cn/fa/51/fa51217eb61badf7eeb09ec2c6ee5f53_960x265.gif) 可以看到:没有中断的线程中断了,但是程序却没有结束。interrupt()不能中断在运行中的线程,它只能改变中断状态而已。 找到interrupt()方法的文档: ![](https://img.kancloud.cn/13/b8/13b820e5063d27008deafae3a7db31b2_1040x342.png) 可以看到如果线程中调用wait,join,sleep会捕获InterruptedException: 我们先用sleep()方法试一下,代码如下: ```java /** * @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()); } } ``` ![](https://img.kancloud.cn/08/75/087549e898bd775555e27b832fed461f_960x265.gif) 再试一下wait()方法: ```java /** * @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()); } } ``` 运行效果如下: ![](https://img.kancloud.cn/16/96/1696ab8c986bd3711ab0e3c9fb3da3bd_960x265.gif) 再试一下join(): ```java /** * @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(); } } } ``` 运行效果如下: ![](https://img.kancloud.cn/4a/5a/4a5ae3ee8d2a4f37b0724a07313eab69_960x205.gif) 线程t1被中断了,但是为什么没收到中断异常呢? 其实join()的是main线程,而我们打断的是t1线程,主线程的join()不会收到中断异常,所以代码改造如下: ```java /** * @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(); } } } ``` 运行效果如下: ![](https://img.kancloud.cn/84/5e/845e863c93eda987efc474213c3cc487_960x205.gif) 同样也捕获到了中断异常,但都没有让t线程退出,我们来看一下join的源码: ![](https://img.kancloud.cn/0b/15/0b1508537a609fd344a60be7da282b4d_652x445.png) 其实join里也是用到了wait()方法的。 那么怎么能让t1线程退出呢,这里有个简单粗暴的方法,但是官方并不推荐,就是stop()方法: 我们在代码的结尾加上 ``` t1.stop(); ``` 运行效果如下: ![](https://img.kancloud.cn/c3/2c/c32c3a5915cd8c6c439bdb2ee2b0fb5e_960x265.gif) 已经实现了我们想要的效果,但是并不推荐这么用,那么到底该怎么优雅的中断线程呢? ## 用一个标记来控制 ```java /** * @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(); } } ``` 运行效果如下: ![](https://img.kancloud.cn/1c/c0/1cc05f651bd17171be39191ed57c5d80_960x205.gif) ## 利用打断机制 ```java /** * @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(); } } ``` 运行效果如下: ![](https://img.kancloud.cn/f0/c2/f0c2d2d4138d6f0041087e46edd3ca98_960x205.gif) 上面两个方法确实可以中断线程,但是有这样一个问题改如何解决呢? ![](https://img.kancloud.cn/b8/60/b860491bfc144760a77473a934987798_685x258.png) 也就是除l了第一次判断了一下interrupted,后面就被阻塞了,那么改如何解决呢?这个我们后续再学习。