本节书摘来自华章社区《java多线程编程核心技术》一书中的第1章,第1.7节停止线程,作者高洪岩,更多章节内容可以访问云栖社区“华章社区”公众号查看
1.7 停止线程
停止线程是在多线程开发时很重要的技术点,掌握此技术可以对线程的停止进行有效的处理。停止线程在java语言中并不像break语句那样干脆,需要一些技巧性的处理。
使用java内置支持多线程的类设计多线程应用是很常见的事情,然而,多线程给开发人员带来了一些新的挑战,如果处理不好就会导致超出预期的行为并且难以定位错误。
本节将讨论如何更好地停止一个线程。停止一个线程意味着在线程处理完任务之前停掉正在做的操作,也就是放弃当前的操作。虽然这看起来非常简单,但是必须做好防范措施,以便达到预期的效果。停止一个线程可以使用thread.stop()方法,但最好不用它。虽然它确实可以停止一个正在运行的线程,但是这个方法是不安全的(unsafe),而且是已被弃用作废的(deprecated),在将来的java版本中,这个方法将不可用或不被支持。
大多数停止一个线程的操作使用thread.interrupt()方法,尽管方法的名称是“停止,中止”的意思,但这个方法不会终止一个正在运行的线程,还需要加入一个判断才可以完成线程的停止。关于此知识点在后面有专门的章节进行介绍。
在java中有以下3种方法可以终止正在运行的线程:
1)使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2)使用stop方法强行终止线程,但是不推荐使用这个方法,因为stop和suspend及resume一样,都是作废过期的方法,使用它们可能产生不可预料的结果。
3)使用interrupt方法中断线程。
这3种方法都会在后面的章节进行介绍。
1.7.1 停止不了的线程
本示例将调用interrupt()方法来停止线程,但interrupt()方法的使用效果并不像for+break语句那样,马上就停止循环。调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。
创建名称为t11的项目,文件mythread.java代码如下:
程序运行结果如图1-28所示。
把eclipse软件中的控制台的日志复制到editplus软件中,确认一下日志是否是50万行,效果如图1-29所示。

从运行的结果来看,调用interrupt方法并没有停止线程。如何停止线程呢?
1.7.2 判断线程是否是停止状态
在介绍如何停止线程的知识点前,先来看一下如何判断线程的状态是不是停止的。在java的sdk中,thread.java类里提供了两种方法。
1)this.interrupted():测试当前线程是否已经中断。
2)this.isinterrupted():测试线程是否已经中断。
interrupted()方法的声明如图1-30所示。
isinterrupted ()方法的声明如图1-31所示。
那么这两个方法有什么区别呢?先来看看this.interrupted()方法的解释:测试当前线程是否已经中断,当前线程是指运行this.interrupted()方法的线程。为了对此方法有更深入的了解,创建项目,名称为t12,类mythread.java代码如下:
程序运行后的结果如图1-32所示。
类run.java中虽然是在thread对象上调用以下代码:
thread.interrupt();
来停止thread对象所代表的线程,在后面又使用以下代码:
system.out.println("是否停止1?="+thread.interrupted());
system.out.println("是否停止2?="+thread.interrupted());
来判断thread对象所代表的线程是否停止,但从控制台打印的结果来看,线程并未停止,这也就证明了interrupted()方法的解释:测试当前线程是否已经中断。这个“当前线程”是main,它从未中断过,所以打印的结果是两个false。
如何使main线程产生中断效果呢?创建run2.java代码如下:
程序运行后的效果如图1-33所示。
从上述的结果来看,方法interrupted()的确判断出当前线程是否是停止状态。但为什么第2个布尔值是false呢?查看一下官方帮助文档中对interrupted方法的解释:
测试当前线程是否已经中断。线程的中断状态由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
文档已经解释得很详细,interrupted()方法具有清除状态的功能,所以第2次调用interrupted()方法返回的值是false。
介绍完interrupted()方法后再来看一下isinterrupted()方法,声明如下:
public boolean isinterrupted()
从声明中可以看出isinterrupted()方法不是static的。
继续创建run3.java类,代码如下:
程序运行结果如图1-35所示。
上面的示例虽然停止了线程,但如果for语句下面还有语句,还是会继续运行的。创建测试项目t13forprint,类mythread.java代码如下:
package exthread;
public class mythread extends thread {
}
类run.java代码如下:
package test;
import exthread.mythread;
public class run {
package testpackage;
文件run.java代码如下:
package test.run;
import testpackage.mythread;
public class synchronizedobject {
文件mythread.java代码如下:
import testpackage.synchronizedobject;
package extthread;
运行类run.java代码如下:
import extthread.mythread;