interrupt()和interrupted()以及isInterrupted()

这一篇着重分析下线程中断,在C.U.T中,中断是用的比较多的一种技术手段,运用的好能带来很多的便利。

1.interrupt()

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

1.如果不是当前线程中断自己,需要checkAccess。

2.如果线程在调用Object类的wait(),join(),sleep()方法过程中受阻,则其中断状态将被清除,同时还收到一个InterruptException。

3.如果该线程在可中断的通道上的 I/O 操作中受阻,则该通道将被关闭,该线程的中断状态将被设置并且该线程将收到一个 ClosedByInterruptException。

4.如果该线程在一个 Selector 中受阻,则该线程的中断状态将被设置,它将立即从选择操作返回,并可能带有一个非零值,就好像调用了选择器的 wakeup 方法一样。

备注:3,4两点本人没什么经验,上述的描述是从jdk api摘抄过来的。一般大家注意下第二点就行。

2.interrupted()

测试当前线程是否已中断。线程的中断状态由该方法擦除。也就是如果两次调用该方法,则第二次会返回false

    public static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

3.isInterrupted()

测试线程是否已被中断,但是线程的状态不受此方法影响。也就是说这个方法不会进行擦除操作

扫描二维码关注公众号,回复: 913783 查看本文章
    public boolean isInterrupted() {
        return isInterrupted(false);
    }
主要的区分就是isInterrupt的调用参数,一个数true,一个是false。
    /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted);

以上就是api内对3个方法的解释,我相信已经很清楚了,没有必要做过多的解释。

以下就是进行一些测试,来分析一下自己的理解。

测试一、使用isInterrupted判断线程状态

public class TestA {
    public static void main(String[] args) {

        T2 t2 = new T2();
        t2.start();

        try{
            Thread.sleep(2000); //主线程执行2S睡眠,保证t2线程能够正常执行一段时间
        }catch (Exception e){
            System.out.println("main exception");
        }

        t2.interrupt(); //通知t2,你中断了

    }
}

class T2 extends Thread {

    @Override
    public void run()
    {
        while (true){
            if(Thread.currentThread().isInterrupted()){
                System.out.println("111111111");
            }else {
                System.out.println("22222222");
            }
            System.out.println("33333333333333");
        }
    }
}
22222222
33333333333333
22222222
33333333333333
22222222
33333333333333
...
...
111111111
33333333333333
111111111
33333333333333
111111111
33333333333333
...
...

结果分析:

可以看见在main线程睡眠的那2秒中内,t2线程在正常执行(输出2,3),当t2进行了中断操作时,输出了(1,3),而我们调用的是isInterrupted方法,这个方法是不会擦除状态的, 同时也要注意,t2线程一直在运行中,没有真正的中断。只是有了一个中断状态而已。

在Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 "

测试二、阻塞方法调用时执行interrupt

public class TestA {
    public static void main(String[] args) {

        T2 t2 = new T2();
        t2.start();

        try{
            Thread.sleep(6000); //主线程执行2S睡眠,保证t2线程能够正常执行一段时间
        }catch (Exception e){
            System.out.println("main exception");
        }

        t2.interrupt(); //通知t2,你中断了

    }
}

class T2 extends Thread {

    @Override
    public void run()
    {
        System.out.println("t2 into sleeping");
        try{
            Thread.sleep(20000);
            System.out.println("t2 wake up");
        }catch (InterruptedException e){
            System.out.println("oh,shit! exception");
            return;
        }
        System.out.println("oh,shit! exception");
    }
}
t2 into sleeping
oh,shit! exception

此测试用例就是测试interrupt方法中API的关于wait,join,sleep方法,如果在调用时发出interrupt指令时,会直接抛出InterruptException。

测试三、阻塞方法调用前执行interrupt方法

public class TestA {
    public static void main(String[] args) {
        System.out.println("main start");
        Thread.currentThread().interrupt();
        try{
            System.out.println("main exe sleep");
            Thread.sleep(6000); //主线程执行2S睡眠,保证t2线程能够正常执行一段时间
            System.out.println("after main exe sleep");
        }catch (InterruptedException e){
            System.out.println("oh! shit Exception");
        }
        System.out.println("main end");
    }
}
main start
main exe sleep
oh! shit Exception
main end
也可以很明显的看见,当主线程执行过interrupt方法之后,如果再执行sleep,wait,join等方法的话,会得到一个InterruptException。
测试四:isInterrupted方法的细节测试
public class TestA {
    public static void main(String[] args) {
        System.out.println("main start");
        Thread.currentThread().interrupt();
        try{
            System.out.println("main exe sleep");
            System.out.println("main state111:  "+Thread.currentThread().isInterrupted());
            Thread.sleep(6000); //主线程执行2S睡眠,保证t2线程能够正常执行一段时间
            System.out.println("after main exe sleep");
        }catch (InterruptedException e){
            System.out.println("oh! shit Exception");
            System.out.println("main state222:  "+Thread.currentThread().isInterrupted());
            System.out.println("main state333:  "+Thread.currentThread().isInterrupted());
        }
        System.out.println("main end");
    }
}
main start
main exe sleep
main state111:  true
oh! shit Exception
main state222:  false
main state333:  false
main end
我们发现,isInterrupted方法只能使用一次,第一次使用时能发现线程处于中断状态了,但是当执行过sleep之后呢,中断状态被擦除了,因此再次判断肯定是false。
测试五、测试interrupted方法
public class TestA {
    public static void main(String[] args) {
        System.out.println("main start");
        System.out.println("main state11:  "+Thread.interrupted());
        Thread.currentThread().interrupt();
        System.out.println("main state22:  "+Thread.interrupted());
        System.out.println("main state33:  "+Thread.interrupted());
        System.out.println("main end");
    }
}
main start
main state11:  false
main state22:  true
main state33:  false
main end
可以发现,当第一次当第二次调用时,可以判断出当前线程处于中断状态了,但是再一次调用时确发现返回了false,因为它做了擦除动作。

猜你喜欢

转载自blog.csdn.net/qq_32924343/article/details/79971109