前言

简答记录一下Thread中断相关的内容。

记录一下,方便自己查阅。

正文

Thread中断主要涉及如下几个方法:

  1. interrupt()

  2. isInterrupted()

  3. interrupted()

下面单独介绍一下。

interrupt()

interrupt()使线程中断。

重点:当线程调用interrupt()时,仅仅设置中断标志位true,此时线程是不会被中断的,会一直执行直到结束。

为了让人易懂,简单测试一下。

测试一

先定义一个MyThread类(比较简单,只是为了测试而已)

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}
MyThread myThreadA = new MyThread("Thread_A");
myThreadA.start();
try {
    Thread.sleep(10);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}
Log.d(TAG, "myThreadA.interrupt() : ");
myThreadA.interrupt();

下面打印日志:

// ...为省略,打印太多了。
run thread name : Thread_A start
...
run thread name : Thread_A [ 102 ]
...
myThreadA.interrupt() 
...
run thread name : Thread_A [ 999 ] 
run thread name : Thread_A end , isInterrupted() : true

从上面可以看出,调用interrupt()后,并不会终止线程中断,直到线程for循环结束,最后打印时中断标志位以为true。

  1. interrupt()会改变中断标志位位true

  2. interrupt()不会打断Thread执行任务,直到自动结束。

测试二

当然,如果线程调用了wait方法、join方法或者sleep方法而被阻塞挂起,此时如果线程A的interrupt(),线程会在调用这些方法的地方抛出InterruptedException异常而返回。

下面我们在ThreadA中的for循环中添加sleep(),其他的保持不变。

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
            try {
                sleep(10);
            } catch (InterruptedException e) {
                Log.d(TAG, "run e: "+ e);
                break;//退出for循环
            }
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}

调用那部分不改变,这里省略,打印日志如下:

run thread name : Thread_A start 
run thread name : Thread_A [ 0 ] 
myThreadA.interrupt() 
run e: java.lang.InterruptedException
run thread name : Thread_A end , isInterrupted() : false

很快就在sleep()中收到InterruptedException,然后我们退出了for循环。

  1. interrupt() 时,如果有sleep()等代码,会抛出InterruptedException

  2. 在1(基础上)抛出异常后最后中断状态为false

也就是说出行InterruptedException后,会影响中断标志位。

由于对Thread源码不是很了解,在,有兴趣的可以看Thread相关的源码。

后续后续有空看一下,这里先插个眼!

isInterrupted()

检测当前线程是否被中断,如果是返回true,否则返回false。

下面测试一下,在ThreadA中新增isInterrupted()判断,如果为true,就结束for循环

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
            if(isInterrupted()){
                Log.d(TAG, "run isInterrupted break: ");
                break;
            }
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}

其他的保持不变[跟interrupt()中代码一样,这里略],打印日志如下:

run thread name : Thread_A start 
run thread name : Thread_A [ 0 ] 
...
myThreadA.interrupt() : 
run thread name : Thread_A [ 100 ] 
run thread name : Thread_A [ 101 ] 
run isInterrupted break: 
run thread name : Thread_A end , isInterrupted() : true

执行中断后,isInterrupted()返回true,然后break退出循环。

  1. interrupt()时,isInterrupted()会返回true

  2. isInterrupted()返回结果后,不会改变中断标志,所以打印依旧为true

interrupted()

如果线程被中断,返回true,否则返回false。

如果interrupted()返回true后,会把中断标志位清除,置为false。

下面简单的测试一下。新增interrupted()判断,如果返回true,就break线程中的for选好

private class MyThread extends Thread {
    public MyThread(String name) {
        setName(name);
    }

    @Override
    public void run() {
        super.run();
        Log.d(TAG, "run thread name : " + getName() + " start ");
        for (int i = 0; i < 1000; i++) {
            Log.d(TAG, "run thread name : " + getName() + " [ " + i + " ] ");
            if(interrupted()){
                Log.d(TAG, "run interrupted break : ");
                break;
            }
        }
        Log.d(TAG, "run thread name : " + getName() + " end , isInterrupted() : " + isInterrupted());
    }
}

执行后日志打印。

run thread name : Thread_A start 
run thread name : Thread_A [ 0 ] 
...
myThreadA.interrupt() : 
run thread name : Thread_A [ 242 ] 
run interrupted break : 
run thread name : Thread_A end , isInterrupted() : false
  1. 调用interrupt()后,interrupted()返回true

  2. interrupted()执行后,把中断标志位置为false

小结

  1. interrupt()设置中断标志位,如果有sleep(),wait()等会抛出InterruptedException

  2. isInterrupted()判断中断标志位是否为true

  3. interrupted()判断中断标志位是否为true,如果当为true,把中断标志位清除(置为false)

  4. interrupted()是静态方法

至于深入Thread源码,暂时没空,先插个眼

参考文章

  1. 《Java并发编程之美》

相关文章

暂无评论

none
暂无评论...