“全栈2019”Java多线程第六章:中断线程interrupt()方法详解

难度

初级

学习时间

30分钟

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJ IDEA v2018.3

友情提示

  • 本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
  • 本章内容针对零基础或基础较差的同学比较友好,可能对于有基础的同学来说很简单,希望大家可以根据自己的实际情况选择继续看完或等待看下一篇文章。谢谢大家的谅解!

1.如何停止线程?

前面在《“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解》一章中讲了如何暂时停止执行线程,现在我们来讲解如何中断线程。

注意:

中断不是终止。

中断:程序中间遇特殊情况须处理,处理完毕之后再继续运行。

终止:程序停止。不再继续运行。

那么怎么让已经在运行的线程停止呢?

在Java中,Thread给出了我们答案:使用stop()方法即可让线程停止运行

但是,由于stop()方法被废弃,所以不能再使用了,我们去看看stop()方法为什么会被废弃。

2.停止线程stop()方法

stop()方法在Thread类中的源码:

去掉注释版:

很遗憾,stop()方法过时了。从@Deprecated(since="1.2")注解也可以看的到:

从JDK1.2开始就已经被弃用了。

为什么stop()方法会被弃用?

这种方法本质上是不安全的。通俗来说会给程序带来意外的异常。

那么问题来了,停止线程的stop()方法被废弃,那么怎么使线程停下来呢?

为此,Java给我们提供了另外一种方式,一种更优雅的方式,使用interrupt()方法中断线程

有小伙伴就提问说:前面你刚刚说过“中断不是终止”,中断线程并不能使线程停止下来啊,你怎么说interrupt()方法能让线程停止?

想要知道答案,请继续往下看。

3.更优雅地停止线程interrupt()方法

首先,我们来看看interrupt()方法在Thread类中源码是什么样的:

将注释翻译成中文:

去掉注释版:

interrupt()方法作用是用来中断线程的。

访问权限

public:interrupt()方法访问权限是公开的。

void:interrupt()方法没有返回值。

interrupt()方法是成员方法,由线程对象调用。

参数

无。

抛出的异常

throws SecurityException:当当前线程无法修改此线程时产生此异常。除非当前线程正在中断自身(始终允许),否则将调用此线程的checkAccess方法,这可能导致抛出SecurityException。

应用

我们来看一下interrupt()方法是如何使用的。

首先,创建一个线程:

然后,我们启动这个线程:

在它启动之后,我们又马上调用了interrupt()方法去中断它:

运行程序,执行结果:

从运行结果来看,根本看不出效果来。

为什么看不出效果?

因为我们在run()方法里面只有一句执行代码,程序执行太快了,还没等到我们去手动停止它,它就已经停止了,所以看不出效果。

既然看不出interrupt()方法效果,那我们应该把run()方法里面的执行代码弄一个无限循环,看线程被中断以后run()方法里面的代码还执行不。

好,就这样干,改写我们的Main类:

运行程序,执行结果:

从运行结果来看,好像并不符合预期结果。

为什么呢?

因为即使我们使用了interrupt()方法,但是线程依旧没有停止下来,所以是不是我们哪里少一步没做还是用错了?

首先,interrupt()方法是中断线程,不是停止线程。所以我们并没有用错interrupt()方法。

其次,现阶段让线程停下来条件只有run方法执行完毕或返回

好像有思路了,我们只要让run()方法执行完毕或返回即可,但是无限循环的话怎么让run()方法执行完毕呢?

无限循环的话我们只需要在循环体中break或return即可

按照上述说法,我们需要在无限循环的循环体根据条件判断即可。

那么,这个判断的条件是什么呢?

Thread类又给我们提供了一个方法:interrupted()方法

interrupted()方法返回当前线程是否已经被中断。

这样的话,我们就可以利用interrupted()方法返回值进行判断,然后让无限循环break或return。

下面我们先来介绍interrupted()方法,然后再去用interrupted()方法改写我们的程序。

4.判断当前线程是否已被中断interrupted()方法

interrupted()方法在Thread类中的源码:

将注释翻译成中文:

去掉注释版:

interrupted()方法的作用就是返回当前线程是否已经被中断。

访问权限

public:interrupted()方法访问权限是公开的。

boolean:interrupted()方法返回当前线程是否已被中断,是返回true,否则返回false。

interrupted()方法是成员方法,由线程对象调用。

参数

无。

抛出的异常

无。

应用

这样的话,interrupt()方法就可以配合interrupted()方法使用。

接下来,我们来改写Main类:

运行程序,执行结果:

从运行结果来看,好像我们没有执行过程序一样,控制台空空如也。

但是又好像我们的interrupt()方法配合interrupted()方法起效果了,我们再来把interrupt()方法执行时机靠后一点,使用前一章学过的sleep()方法使主线程睡3秒。

接着,我们来改写Main类:

再次运行程序,执行结果:

从运行结果来看,符合我们的预期。

这次线程是真的停下来了。

但是,我们好像还发现了一个和interrupted()方法类似的方法,在这可以寻找到:

就是这个“@see #isInterrupted()”,这个注解我们前面几章讲解过了,这里就不再赘述。它是参见的意思。

下面,我们就去看看isInterrupted()方法。

5.判断当前线程是否已被中断isInterrupted()方法

isInterrupted()方法在Thread类中的源码:

将注释翻译成中文:

去掉注释版:

isInterrupted()方法作用就是判断当前线程是否已经被中断。

访问权限

public:isInterrupted()方法访问权限是公开的。

boolean:isInterrupted()方法返回当前线程是否已被中断,是返回true,否则返回false。

isInterrupted()方法是成员方法,由线程对象调用。

参数

无。

抛出的异常

无。

应用

既然isInterrupted()方法和interrupted()方法类似,那我们就来用isInterrupted()方法改写我们的Main类试试:

运行程序,执行结果:

从运行结果来看,符合我们的预期。

那么,isInterrupted()方法和interrupted()方法有什么区别呢?

下面我们就来看看。

6.isInterrupted()方法和interrupted()方法的区别

要弄清isInterrupted()方法和interrupted()方法之间的区别还得从它们的源码看起。

首先是interrupted()方法源码:

再者,是isInterrupted()方法源码:

大家看到了吗?

interrupted()方法和isInterrupted()方法都调用了isInterrupted(boolean ClearInterrupted)方法,只不过呢,interrupted()方法调用传参是true:

isInterrupted()方法调用传参是false:

这个参数是什么意思呢?

参数的意思是是否清除中断状态

如果是true,就代表需要将中断状态清除。

如果是false,就代表不需要将中断状态清除。

中断状态是什么?

怎么说呢,就是说我们给需要中断的线程一个状态(标记)。

中断状态什么时候被设置?

当我们调用interrupt()方法时,中断状态就被设置上了。

当中断状态被设置时,下一次你使用interrupted()方法或isInterrupted()方法时,这两个方法就会去判断线程的中断状态是否为中断状态,如果为中断状态,那么就返回true,如果不为中断状态就返回false。

当你调用interrupted()方法时,除了返回当前线程是否已被中断以外,还把中断状态给清除了,所以后面你再第二次调用interrupted()方法时,就直接返回false了,因为之前的一次调用已经把中断状态给清除了。

而调用isInterrupted()方法则不会清除中断状态。

总结

  • interrupt()方法作用是用来中断线程的。
  • interrupted()方法的作用就是返回当前线程是否已经被中断。
  • isInterrupted()方法作用就是判断当前线程是否已经被中断。
  • 我们给需要中断的线程一个状态(标记),如果它需要被中断呢,就给它打上一个中断标记(也叫中断状态),下一次你使用interrupted()方法或isInterrupted()方法时,这两个方法就会去判断线程的中断状态是否为中断状态,如果为中断状态,那么就返回true,如果不为中断状态就返回false。
  • 当你调用interrupted()方法时,除了返回当前线程是否已被中断以外,还把中断状态给清除了,所以后面你再第二次调用interrupted()方法时,就直接返回false了,因为之前的一次调用已经把中断状态给清除了。
  • 而调用isInterrupted()方法则不会清除中断状态。

至此,Java中中断线程interrupt()方法相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java多线程第五章:线程睡眠sleep()方法详解

下一章

“全栈2019”Java多线程第七章:等待线程死亡join()方法详解

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

版权声明

原创不易,未经允许不得转载!

了解更多
举报
评论 0