在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,后面就被阻塞了,那么改如何解决呢?这个我们后续再学习。
- 微服务
- 服务器相关
- 操作系统
- 极客时间操作系统实战笔记
- 01 程序的运行过程:从代码到机器运行
- 02 几行汇编几行C:实现一个最简单的内核
- 03 黑盒之中有什么:内核结构与设计
- Rust
- 入门:Rust开发一个简单的web服务器
- Rust的引用和租借
- 函数与函数指针
- Rust中如何面向对象编程
- 构建单线程web服务器
- 在服务器中增加线程池提高吞吐
- Java
- 并发编程
- 并发基础
- 1.创建并启动线程
- 2.java线程生命周期以及start源码剖析
- 3.采用多线程模拟银行排队叫号
- 4.Runnable接口存在的必要性
- 5.策略模式在Thread和Runnable中的应用分析
- 6.Daemon线程的创建以及使用场景分析
- 7.线程ID,优先级
- 8.Thread的join方法
- 9.Thread中断Interrupt方法学习&采用优雅的方式结束线程生命周期
- 10.编写ThreadService实现暴力结束线程
- 11.线程同步问题以及synchronized的引入
- 12.同步代码块以及同步方法之间的区别和关系
- 13.通过实验分析This锁和Class锁的存在
- 14.多线程死锁分析以及案例介绍
- 15.线程间通信快速入门,使用wait和notify进行线程间的数据通信
- 16.多Product多Consumer之间的通讯导致出现程序假死的原因分析
- 17.使用notifyAll完善多线程下的生产者消费者模型
- 18.wait和sleep的本质区别
- 19.完善数据采集程序
- 20.如何实现一个自己的显式锁Lock
- 21.addShutdownHook给你的程序注入钩子
- 22.如何捕获线程运行期间的异常
- 23.ThreadGroup API介绍
- 24.线程池原理与自定义线程池一
- 25.给线程池增加拒绝策略以及停止方法
- 26.给线程池增加自动扩充,闲时自动回收线程的功能
- JVM
- C&C++
- GDB调试工具笔记
- C&C++基础
- 一个例子理解C语言数据类型的本质
- 字节顺序-大小端模式
- Php
- Php源码阅读笔记
- Swoole相关
- Swoole基础
- php的五种运行模式
- FPM模式的生命周期
- OSI网络七层图片速查
- IP/TCP/UPD/HTTP
- swoole源代码编译安装
- 安全相关
- MySql
- Mysql基础
- 1.事务与锁
- 2.事务隔离级别与IO的关系
- 3.mysql锁机制与结构
- 4.mysql结构与sql执行
- 5.mysql物理文件
- 6.mysql性能问题
- Docker&K8s
- Docker安装java8
- Redis
- 分布式部署相关
- Redis的主从复制
- Redis的哨兵
- redis-Cluster分区方案&应用场景
- redis-Cluster哈希虚拟槽&简单搭建
- redis-Cluster redis-trib.rb 搭建&原理
- redis-Cluster集群的伸缩调优
- 源码阅读笔记
- Mq
- ELK
- ElasticSearch
- Logstash
- Kibana
- 一些好玩的东西
- 一次折腾了几天的大华摄像头调试经历
- 搬砖实用代码
- python读取excel拼接sql
- mysql大批量插入数据四种方法
- composer好用的镜像源
- ab
- 环境搭建与配置
- face_recognition本地调试笔记
- 虚拟机配置静态ip
- Centos7 Init Shell
- 发布自己的Composer包
- git推送一直失败怎么办
- Beyond Compare过期解决办法
- 我的Navicat for Mysql
- 小错误解决办法
- CLoin报错CreateProcess error=216
- mysql error You must reset your password using ALTER USER statement before executing this statement.
- VM无法连接到虚拟机
- Jetbrains相关
- IntelliJ IDEA 笔记
- CLoin的配置与使用
- PhpStormDocker环境下配置Xdebug
- PhpStorm advanced metadata
- PhpStorm PHP_CodeSniffer