简述
停止线程在多线程的开发中是非常重要的一点,掌握这个技术可以对线程的停止进行非常有效的处理。当然了停止线程肯定不会像break那样或者goto那种直接就停止或者跳转,需要一些技巧性的处理。
方法
停止一个线程可以使用Thread.stop()方法,但是最好不要使用,虽然说它可以很快的停止一个正在运行中的线程,但是但是但是这个方法是不安全的,而且是已经被用作废的,并且在未来的Java版本中,很有可能这个方法将不可以使用了或者不被支持
大多数的停止线程操作常用Thread.interrupt()方法,但是呢虽然这个方法的名称是“停止”、“中止”的感觉,但是这个方法不会终止一个正在运行的线程,还需要加入一些判断才可以完成线程的停止,这个在我之后的一篇博客会专门介绍
总的来说,在Java中有三种方法可以中止正在运行的线程:
①使用退出标志,使得线程正常的退出,也就是直接在run结束了,那么这个线程也就自然而然的终止了
②使用stop强行终止,前面说过了,不推荐这个方法,就像suspend一样,是作废过期的方法,使用了可能会产生不可预料的结果
③使用interrupt方法中断线程
停止不了的线程
package MyThread;
public class mythread extends Thread{
@Override
public void run() {
super.run();
for(int i=0;i<500000;i++)
{
System.out.println("i="+(i+1));
}
}
}
run一下:
package test;
import MyThread.mythread;
import MyThread.CountOperate;
public class Run {
public static void main(String[] args) {
try {
mythread my=new mythread();
my.start();
Thread.sleep(2000);
my.interrupt();
}catch(InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
运行结果:
在run类里使用了interrupt,但是由结果可以发现,好像并没有什么用,那么我们该怎么停止线程呢?
先判断停止状态
在要停止一个线程之前我们总得要先判断一下这个线程状态是否是活跃的,在Java的SDK中,Thread.java类里提供了两种方法:
1)this.interrupted():测试当前线程是否已经中断
2)this.isInterrupted():测试线程是否已经中断
现在看一下他们的方法声明:
interrupted
public static boolean interrupted()
isInterrupted
public boolean isInterrupted()
那么他们的区别是什么捏
先看一下this.interrupted(),前面说了是测试当前线程是否中断,当前线程是指运行this.interrupted()方法的线程,为了更加的深入,举个小栗子:
package MyThread;
public class mythread extends Thread{
@Override
public void run() {
super.run();
for(int i=0;i<50;i++)
{
System.out.println("i="+(i+1));
}
}
}
package test;
import MyThread.mythread;
import MyThread.CountOperate;
public class Run {
public static void main(String[] args) {
try {
mythread my=new mythread();
my.start();
Thread.sleep(1000);
my.interrupt();
System.out.println("是否停止 1?="+Thread.interrupted());
System.out.println("是否停止 2?="+Thread.interrupted());
}catch(InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
运行结果:
在我们加上了判断thread对象所代表的线程是否停止,但从控制台打印的结果来看,线程并没有停止,那么这也证明了interrupted()方法的解释:测试当前线程是否已经中断,在这里由于“当前线程”是main,他从未中断过,所以打印出来的结果是两个false,那么现在如果说我想要中断main线程该怎么做呢,下面再看一个例子:
package test;
public class Run2{
public static void main(String[] args){
Thread.currentThread().interrupt();
System.out.println("是否停止1?="+Thread.interrupted());
System.out.println("是否停止2?="+Thread.interrupted());
System.out.println("测试结束!");
}
}
运行结果:
从这个结果来看,方法interrupted()的确判断处理当前线程是否处于停止状态,那么为什么第二个布尔值是false呢?
在这里官方文档对于interrupted方法的解释是这样的:
测试当前的线程是否已经中断,线程的中断状态由该方法清除
在这里解释一下,第二次调用之所以会返回false,是因为在第一次调用的时候已经清除了其中断状态之后,且第二次调用检测完中断状态之前,那么当前线程再次中断的情况是除外的
也就是说,interrupted()方法具有清除状态的功能,所以第二次在调用的时候返回的是false
介绍完了interrupted()方法,现在来看isInterrupted()方法
在前面的方法声明可以看到,这个方法和上一个方法很大的一个区别就是这个方法不是static的,现在举个例子看看这个方法具体的运用:
package MyThread;
public class mythread extends Thread{
@Override
public void run() {
super.run();
for(int i=0;i<50;i++)
{
System.out.println("i="+(i+1));
}
}
}
run:
package test;
import MyThread.mythread;
public class Run2{
public static void main(String[] args){
try {
mythread my=new mythread();
my.start();
Thread.sleep(1000);
my.interrupt();
System.out.println("是否停止1?="+my.isInterrupted());
System.out.println("是否停止2?="+my.isInterrupted());
}catch(InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
}
运行结果:
在这里可以看到,方法isInterrupted()并没有清除状态的功能,我中断了,就是中断了,已经就停止了,所以打印了两个true
总结
1)this.interrupted():测试当前线程是否已经中断,执行后具有将状态标志置清除为false的功能
2)this.isInterrupted():测试线程Thread对象是否已经中断,但是不清除标志状态