线程中断

线程中断

前言

一直对java线程的中断有点模糊的感觉,决心要弄清楚。

interrupted,isInterrupted,interrupt

	Thread.interrupted();//清除中断标志,并返回清除前的值
    Thread.currentThread().isInterrupted();//判断中断标志
    Thread.currentThread().interrupt();//设置中断为true
    我是这样理解的 线程中断标志默认 flag=false
    interrupt方法把他改为true
    isInterrupted方法返回flag,true代表中断,false代表未被中断
    interrupted返回flag,并且重置flag=false

测试interrupted

由于interrupted最复杂,着重于测试这个方法,代码如下

	Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                }
            }
        });
        t.start();
        System.out.println("1:"+t.isInterrupted());
        t.interrupt();//中断
        System.out.println("2:"+t.isInterrupted());
        System.out.println("3:"+t.interrupted());
        System.out.println("4:"+t.isInterrupted());

如果按照我们之前的分析,那么输出结果应该如下所示

1:false
2:true
3:true
4:false

可是实际的结果如下

1:false
2:true
3:false
4:true

从这个结果可以看出来线程t一直是中断的状态
那么 t.interrupted() 这行代码为什么没有重置 t 线程的flag=false呢?

跟进interrupted源码看看

	public static boolean interrupted() {
		//原因在这里 currentThread()!=t 
        return currentThread().isInterrupted(true);
    }

下面我们来确定 currentThread()!=t

	 Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                }
            }
        });
        t.start();
        System.out.println("t:"+t);
        System.out.println("main:"+Thread.currentThread());
        System.out.println("1:"+t.isInterrupted());
        t.interrupt();//中断
        System.out.println("2:"+t.isInterrupted());
        System.out.println("3:"+t.interrupted());
        System.out.println("4:"+t.isInterrupted());

我们在interrupted源码里打个断点,debug执行,选中currentThread()后右键选择Evaluate Expression执行的result=Thread[main,5,main]
在这里插入图片描述控制台输出结果是

t:Thread[Thread-0,5,main]
main:Thread[main,5,main]
1:false
2:true
3:false
4:true

问题已经定位清楚了,下面我们来写一个正确的例子来证明interrupted确实有清除中断标志,并返回清除前的值这两个功能。

	public static void main(String[] args) throws InterruptedException {
        System.out.println("1:"+Thread.currentThread().isInterrupted());
        Thread.currentThread().interrupt();
        System.out.println("2:"+Thread.currentThread().isInterrupted());
        System.out.println("3:"+Thread.interrupted());
        System.out.println("4:"+Thread.currentThread().isInterrupted());
    }

输出,可以看出来interrupted确实生效了

1:false
2:true
3:true
4:false

如何优雅的停止线程

方案一:volatile

优点:代码简单
缺点:停止不及时
代码如下:
我们的本意是1s后停止线程,可是却等到10s后才停止。

	private static volatile boolean flag=true;
   
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(flag){
                    System.out.println("run");
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        Thread.sleep(1000);
        flag = false;
    }

方案二:利用中断

	public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
            	//flag==false
                while(!Thread.currentThread().isInterrupted()){
                    System.out.println("run");
                    try {
                        Thread.sleep(10000);//发现中断标志flag = true,重置flag = false,响应中断进入catch
                    } catch (InterruptedException e) {
                        System.out.println("catch:"+Thread.currentThread().isInterrupted());//catch:false
                        Thread.currentThread().interrupt();//再次中断,即可立即退出线程
                    }
                }
            }
        });
        t.start();
        Thread.sleep(1000);
        t.interrupt();//flag = true
    }

个人不喜欢interrupted这个操作,我也尽量避免书写一些一个函数干多个事情的的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值