(三)java并发编程系列之安全中断线程

本文重点讲述如何中断一个正在运行中的线程

下面我们首先来看看常用的几个中断的方法:
第一个叫做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线程工作的方法,如有疑问欢迎提问,共同探讨

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值