本文重点讲述如何中断一个正在运行中的线程
下面我们首先来看看常用的几个中断的方法:
第一个叫做stop(),还有一suspend(),下面首给出源码
@Deprecated
public final void stop() {.........}
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
大家注意看这两个方法都有一个相同的注解@Deprecated,由于英文不太好,我特地在网上查了以下这个单词
也就是说,官方现在也不赞同使用这两个方法,为什么呢?我这里直接给出答案,就是会出现线程安全问题,大家可以想以下,一个线程正在直接,你直接暴力终止,线程内部的运行逻辑还没有完成,那么是不是造成数据错误或者数据的不完全,一旦出现数据不完全,对于使用者来着就是灾难级别的,所以这两个方法不赞成使用,那么怎么办呢?java 既然不建议使用这两个,肯定给除了一个安全的中止办法,,下面我为大家细细道来:
首先有三个方法先给大家做一个解释:
interrupt() 标记一个中断位,标记为true ,不会直接中断 ,一定是在线程外部调用,
isInterrupted() 判断中断标记位是否为true
static 方法的 interrupted 方法 判断中断标记位是否为true,同时判断完成后,把这个标记位改变为false
下面为大家演示以下正确的中断方法:
package com.feitian.thread.end;
/**
* @author feiTian
* @date 2019/2/19 1:21
* @package com.feitian.thread.end
* @descb 描述:安全中断线程
**/
public class EndThread extends Thread {
@Override
public void run() { isInterrupted 判断标记位是否位true,如果是true,就进行中断操作
while (!isInterrupted()){
System.out.println(Thread.currentThread().getName()+" 继续走起");
}
System.out.println(Thread.currentThread().getName()+" 被 中断了 "+isInterrupted());
}
}
package com.feitian.thread.end;
/**
* @author feiTian
* @date 2019/2/19 1:23
* @package com.feitian.thread.end
**/
public class EndDemo {
public static void main(String [] args) throws InterruptedException {
Thread thread = new EndThread ();
thread.start();
Thread.sleep(500);
thread.interrupt(); //标记中断位,设置中断标记为true
}
}
休眠是为了保证线程内部执行完毕。大家可以把代码直接copy下去进行测试。
下面为大家演示以下中断 通过实现Runnable接口创建的线程:
package com.feitian.thread.end;
/**
* @author feiTian
* @date 2019/2/19 1:05
* @package com.feitian.thread.start
* @desc 描述:安全中断线程
**/
public class EndRunnable implements Runnable {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().isInterrupted());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" 被 中断了 "+Thread.currentThread().isInterrupted());
}
}
package com.feitian.thread.end;
/**
* @author feiTian
* @date 2019/2/19 1:23
* @package com.feitian.thread.end
**/
public class EndDemo {
public static void main(String [] args) throws InterruptedException {
Thread thread = new Thread(new EndRunnable());
thread.start();
Thread.sleep(500);
thread.interrupt(); //标记中断位,设置中断标记为true
}
}
这段代码大家也可以去执行以下,会发现出现了中断异常
那么到底是为什么会出现这段异常呢?
经过大量查寻资料,发现 我们启动的 main也是一个线程而且是一个主线程,EndRunnable是一个子线程,然而单元测试启动主线程很快的执行完毕了,当主线程要强制中断子线程的时候,却发现子线程还在休眠当中,就出现了主线程时间不足,那么此时子线程也就不会判断标记位是否为true,从而造成了这个异常。那么解决办法就是在异常处理哪里再次调用中断标记位方法,把标记位重新置为true,就可以了
具体操作如下
public class EndRunnable implements Runnable {
@Override
public void run() {//isInterrupted 判断标记位是否位true,如果是true,就进入判断中,进行中断操作
while (!Thread.currentThread().isInterrupted()){
System.out.println(Thread.currentThread().isInterrupted());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); //再次调用中断标记位,把标记位置为true,下个循环就正确中断线程了
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+" 被 中断了 "+Thread.currentThread().isInterrupted());
}
}
这样就可以正常中断线程了,Callable的中断和这个一样的操作,好了,这里就是关于如何安全停止Java线程工作的方法,如有疑问欢迎提问,共同探讨