java并发:中断一个正在运行的线程
要使任务和线程能安全可靠地停止,并不是一件很容易的事情,java没有提供任何机制来安全地终止线程,那么我们该怎么办呢?
下面我们先来了解一下java中的中断机制:
Java 中的线程中断是 一种线程间的协作机制。
也就是说在某个线程中对另一个线程调用interrupt()方法并不能直接终止该线程,需要被中断的线程自己处理中断请求
isInterrupted()和interrupted() 的主要区别
非静态方法isInterrupted()用来查询某线程的中断状态,且不会改变该线程的中断状态标识。
源代码的定义如下:
/** * Tests whether this thread has been interrupted. The <i>interrupted * status</i> of the thread is unaffected by this method. * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return {@code true} if this thread has been interrupted; * {@code false} otherwise. * @see #interrupted() * @revised 6.0 */ public boolean isInterrupted() { return isInterrupted(false); }
/** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ @HotSpotIntrinsicCandidate private native boolean isInterrupted(boolean ClearInterrupted);
静态方法interrupted()检查中断状态时,中断状态会被清零(置为false)。
调用方式如下:
源代码的定义如下:
/** * Tests whether the current thread has been interrupted. The * <i>interrupted status</i> of the thread is cleared by this method. In * other words, if this method were to be called twice in succession, the * second call would return false (unless the current thread were * interrupted again, after the first call had cleared its interrupted * status and before the second call had examined it). * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return {@code true} if the current thread has been interrupted; * {@code false} otherwise. * @see #isInterrupted() * @revised 6.0 */ public static boolean interrupted() { return currentThread().isInterrupted(true); }
/** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ @HotSpotIntrinsicCandidate private native boolean isInterrupted(boolean ClearInterrupted);
小结:
从上述源代码的定义可以看到,isInterrupted()和interrupted() 调用了同一个native方法,但是传递的参数不一样。
示例
例一
在下面的例子中,主线程通过调用t.interrupt()方法将线程t的中断状态设置为true,线程t可以在合适的时候调用interrupted()方法或isInterrupted()方法来检测其中断状态并做相应处理:
package com.test; public class ThreadTest extends Thread { public void run() { while (true) { if (Thread.interrupted()) { System.out.println("Someone interrupted me."); break; } else { System.out.println("Going..."); } long now = System.currentTimeMillis(); while (System.currentTimeMillis() - now < 1000) { //让循环持续一段时间,打印的输出语句会少一些 } } } public static void main(String[] args) throws InterruptedException { ThreadTest t = new ThreadTest(); t.start(); Thread.sleep(3000); t.interrupt(); } }
结果如下:
Going...
Going...
Going...
Someone interrupted me.
结论:
(1)对于非阻塞中的线程, 只是改变了中断状态, 即Thread.isInterrupted()将返回true;
(2)对于可取消的阻塞状态中的线程, 比如等待在Thread.sleep(), Object.wait(), Thread.join(),这些函数上的线程, 这个线程收到中断信号后, 会抛出InterruptedException, 同时会把中断状态置回为false.
例二
下面这段程序会使得阻塞在Thread.join()方法上的主线程在收到中断信号后结束:
package com.test; public class ThreadTest extends Thread { private Thread parent; public ThreadTest(Thread parent){ this.parent = parent; } public void run() { while (true) { System.out.println("sub thread is running..."); long now = System.currentTimeMillis(); while (System.currentTimeMillis() - now < 2000) { //让循环持续一段时间,打印的输出语句会少一些 } parent.interrupt(); } } public static void main(String[] args){ ThreadTest t = new ThreadTest(Thread.currentThread()); t.start(); try { t.join(); } catch (InterruptedException e) { System.out.println("Parent thread will die..."); } } }
结果如下:
sub thread is running...
Parent thread will die...
sub thread is running...
sub thread is running...
sub thread is running...
sub thread is running...
从结果可以看出,线程t发出中断请求后主线程结束(此时线程t仍在运行)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?