前言
在网上看了几篇关于线程中断三个方法的相关文章,写的都很官方,对于初学者来说,不易理解透彻,于是决定把自己的探索结果和学习总结分享给大家。本次探索过程使用的jdk本版为:1.8.0_171。
java中的线程中断是什么?
- 错误理解: 线程中断,从字面上来理解,第一感觉就是线程中断了,停止运行了,这是错误的理解哈。
- 通俗正确理解: 线程中断可以理解为,它是线程对象的一个属性,key为线程中断状态,value为true or false,默认值为false,是线程通信的手段之一。
- jdk创作者设计它的初衷 是为了提供一种手段给基于jdk编程的程序员,可用于解决在线程相互调用过程中,可能会出现线程阻塞或死锁而导致程序长时间或永久无法运行的故障。
线程中断的三个方法
线程中断状态值默认返回false,如果被中断则状态值为true,未被中断则值为false,中断状态被清除则值为false。以下表格备注列为常用的描述,具体参见jdk方法注释文档
方法名 | 方法描述 | 备注 |
---|---|---|
public void interrupt() | 中断此线程 | 如果在调用Object类的wait(),wait(long)或wait(long,int)方法或join(),join(long),join(long,int)方法时阻塞了此线程,sleep(long)或sleep(long,int)此类的方法,则其中断状态将被清除,并将收到InterruptedException |
public boolean isInterrupted() | 测试此线程是否已被中断 | 线程的中断状态不受此方法的影响 |
public static boolean interrupted() | 测试当前线程是否已被中断 | 通过此方法可以清除线程的中断状态。 换句话说,如果要连续调用此方法两次,则第二次调用将返回false(除非当前线程在第一次调用清除其中断状态之后且在第二次调用检查其状态之前再次中断) |
总结
一个静态方法: interrupted()
两个成员方法: isInterrupted(),interrupt()
一个用于线程通信: interrupt(),A线程想向B线程发起中断通知new B().interrupt()
两个用于获取线程中断状态值: interrupted(),isInterrupted()。前者为当前线程感知自身的中断状态Thread.interrupted(),并立即设置自身中断状态值为false;后者为A线程想感知B线程的中断状态,在A线程中调用代码new B().isInterrupted(),不改变B的中断状态。
使用场景
结束线程的三种方法(非循环代码,执行完自动结束,此处介绍需要使用循环来处理的多线程场景,如监听程序等等):
- 设置退出标识boolean,配合volatile 关键字
public class ThreadFlag extends Thread {
public volatile boolean exit = false;
public void run() {
while (!exit);
}
public static void main(String[] args) throws Exception {
ThreadFlag thread = new ThreadFlag();
thread.start();
sleep(5000);
//设置退出标识
thread.exit = true;
thread.join();
System.out.println("线程退出!");
}
}
- 使用stop()方法,不推荐
- 使用线程中断,小编最推荐的一种方式(下面示例为阻塞线程的终止,非阻塞线程的终止,无需catch中的处理即可)
public class InterruptTest extends Thread{
@Override
public void run() {
//线程中断状态值默认为false,此线程一开始是可以进入while执行的
while(!isInterrupted()) {
try {
sleep(500);
} catch (InterruptedException e) {
//如果发生线程中断异常,此线程的中断状态被清除,为false,while循环还会继续执行
System.out.println(Thread.currentThread().getName() + ":发生中断异常后,中断状态为:" + isInterrupted());
e.printStackTrace();
//发生中断异常,应该结束掉该线程,结束while循环即可。
//中断自身线程操作,不可使用静态interrupted方法,否则中断状态值仍未false,无法结束。应该使用interrupt方法
interrupt();
System.out.println(Thread.currentThread().getName() + ":发生中断异常且调用interrupt()后,中断状态为:" + isInterrupted());
}
}
System.out.println(Thread.currentThread().getName() + "线程结束");
}
public static void main(String[] args) {
Thread thread = new InterruptTest();
thread.setName("测试线程中断使用场景的线程");
thread.start();
try {
//主线程休眠
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}