线程的中断机制是多线程编程中的一个重要概念,用于协调和控制线程的执行。中断可以看作是一种线程间的通信机制,允许一个线程请求另一个线程停止正在进行的工作。线程的中断机制是一种协作式的机制,不会强制性地停止一个线程。
1. 中断的基本概念
- 中断标志:每个线程都有一个
boolean
类型的中断状态标志。通过调用Thread.interrupt()
方法,可以将某个线程的中断状态设置为true
,从而请求该线程中断其执行。 - 被中断的响应:线程在执行过程中可以通过检查自身的中断状态(通过
Thread.interrupted()
或isInterrupted()
方法)来判断是否被中断,并在适当的时候做出响应。
2. 中断的方法和响应
- Thread.interrupt():
- 调用这个方法会设置线程的中断状态为
true
。 - 如果线程在等待状态(如
sleep()
、wait()
、join()
等方法),或者在可中断的阻塞方法(如BlockingQueue
的take()
方法)中被阻塞,那么它将抛出InterruptedException
异常,以响应中断。
- 调用这个方法会设置线程的中断状态为
- Thread.interrupted():
- 静态方法,用于测试当前线程的中断状态,并清除该状态(将中断状态重置为
false
)。 - 常用于检查当前线程是否被中断,并在需要时进行处理。
- 静态方法,用于测试当前线程的中断状态,并清除该状态(将中断状态重置为
- isInterrupted():
- 实例方法,用于测试线程对象的中断状态,但不会改变中断状态。
- 可以在线程的运行逻辑中定期检查该方法,来决定是否继续执行任务或者停止执行。
3. 中断的使用场景
- 安全地停止线程:通过中断机制可以安全、优雅地停止线程的执行,而不是强制性地使用
stop()
方法,从而避免因突然终止导致的资源泄漏或数据不一致性。 - 响应取消请求:允许线程在接收到中断请求时,尽快地停止当前的工作,释放资源或清理状态。
- 线程间协作:通过中断机制,可以实现线程之间的协作和控制,例如在多个线程之间传递信号以请求终止或切换执行。
4. 示例代码
public class Test6_interrupt {
public static void main(String[] args) {
/**
* interrupt() 设置线程为中断状态
* interrupted() 在检测完之后会清除线程的中断状态,修改为false
* isInterrupted() 在检测完之后不会清除线程的中断状态(它比较单纯,只做判断)
*/
System.out.println(Thread.currentThread().getName() +"线程数是否被中断:"+Thread.interrupted());//false
// 设置主线程 中断信号
Thread.currentThread().interrupt();中断标志被设置为true
// Thread.currentThread().stop();//已被弃用,太黄太暴力了(会导致线程被强制停止),会导致数据的丢失
System.out.println(Thread.currentThread().getName() +"线程数是否被中断:"+Thread.interrupted()); //true
System.out.println(Thread.currentThread().getName() +"线程数是否被中断:"+Thread.interrupted());//false,中断标志被还原
// 设置主线程 中断信号
Thread.currentThread().interrupt();//中断标志被设置为true
// 中断标志不会被还原
System.out.println(Thread.currentThread().getName() +"线程数是否被中断:"+Thread.currentThread().isInterrupted()); //true
System.out.println(Thread.currentThread().getName() +"线程数是否被中断:"+Thread.currentThread().isInterrupted());//true
}
}
5.中断恢复策略
先看代码
public class Test7_isInterrupted {
public static void main(String[] args) {
Thread thread = Thread.currentThread();
System.out.println(thread.getName()+"线程是否中断:"+thread.isInterrupted());//false
thread.interrupt();//设置中断状态为true
System.out.println(thread.getName()+"线程是否中断:"+thread.isInterrupted());//true
System.out.println(thread.getName()+"线程是否中断:"+thread.isInterrupted());//true
try {
// 线程休眠5秒
Thread.sleep(2000);//本来主线程要被休眠2秒的,但是因为interrupt被调用,所以sleep被打断
System.out.println("线程休眠未被中断");
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("线程休眠被中断");
// 判断线程是否中断,因为异常已经被处理,所以状态回复为false,扩展:在catch中写处理代码
System.out.println(thread.getName()+"线程是否中断:"+thread.isInterrupted());//false
}
// isInterrupted()不会恢复线程的中断状态
System.out.println(thread.getName()+"线程是否中断:"+thread.isInterrupted());//false
}
}
因为主程序调用thread.interrupt();设置中断状态为true。所以在执行休眠时,会被打断并抛出异常,当进入catch块处理异常时,我们打印当前线程的中断状态时我们会发现,此时的中断状态已经被恢复了。这就是所谓的中断恢复策略。
为什么要恢复中断状态?
- 传递中断请求: 恢复中断状态可以传递中断请求给更高级别的代码,使得整个应用能够正确响应中断。
- 保持响应性: 保证后续的阻塞操作能够正确检测到中断状态,并做出相应的处理,这样可以更好地控制线程的行为和状态。