interrupt、interrupted、isInterrupted方法详解

interrupt方法的源码:

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

    synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
        	interrupt0();  //仅仅对当前线程的中断位进行标记
        	b.interrupt();
        	return;
        }
    }
    interrupt0();     // Just to set the interrupt flag
}

源码说明:
private volatile Interruptible blocker;
private native void interrupt0();
变量blocker表示中断状态(interrupt status),blocker的值默认是null。 interrupt0()方法是本地方法,其作用是仅仅对当前线程的中断位进行标记。线程的中断标志位默认是false,interrupt0()方法将线程的中断标志位设置为true,设置线程的中断状态。清除线程的中断状态,就是将中断标志位设置为false。

当线程调用interrupt方法时,会进入到同步代码块中,由于blocker==null,所以不执行if语句中的代码,而是调用interrupt0()方法,将线程的中断标志位设置为true。所以调用interrupt方法不能中断线程,只是设置线程的中断状态

调用sleep、wait或join等方法的线程,如果再调用interrupt方法,将会抛出InterruptedException异常,或者调用interrupt方法的线程,如果再调用sleep、wait或join等方法,也会抛出InterruptedException异常。

interrupted和isInterrupted方法的源码:

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

public boolean isInterrupted() {
    return isInterrupted(false);
}

private native boolean isInterrupted(boolean ClearInterrupted);

interruptedisInterrupted方法的相同点都是判断线程的中断状态(interrupted status)是否被设置(即标志位是否为true),若被设置返回true,否则返回false。区别有两点:一:前者是static方法,调用者是current thread,而后者是普通方法,调用者是this thread。二:它们其实都调用了Java中的一个native方法isInterrupted(boolean ClearInterrupted); 不同的是前者传入了参数true,后者传入了false,意义就是:前者将清除线程的interrupt state(将线程的中断标志位设置为false),后者对线程的interrupt state没有影响。

public void interrupt();

向线程发送中断请求,线程的中断标志位将被设置为true。如果线程在调用 Object 类的 wait()wait(long) 或 wait(long, int) 方法,或者Thread类的join()join(long)join(long, int)sleep(long) 或 sleep(long, int) 方法过程中受阻,将抛出InterruptedException异常,且线程的中断状态将被清除。

调用interrupt方法是在线程中打了一个停止标志,并不是真的停止线程。其作用是中断此线程此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。可通过interrupted和isInterrupted方法判断中断标志,进而结束线程。此线程是指调用interrupt方法的线程,如Thread t = new Thread();t.interrupt();线程t调用了interrupt方法,所以此线程就是指线程t

public static boolean interrupted();

如果当前线程已经中断,则返回 true;否则返回 false。

interrupted方法的作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态。由于第一次调用interrupted方法时,中断状态已经被清除,第二次再调用interrupted方法时将返回一个false。在哪个线程中调用了interrupted方法,该线程就是当前线程,如在main线程中有如下语句,Thread t = new Thread();t.interrupted();虽然是线程t调用了interrupted方法,但是,是在main线程中调用的interrupted方法,main线程就是当前线程

public boolean isInterrupted();

如果此线程已经中断,则返回 true;否则返回 false。

测试线程是否已经中断,线程的中断状态不受该方法的影响。作用是只测试此线程是否被中断,不清除中断状态。此线程是指调用isInterrupted方法的线程,如在main线程中有如下语句,Thread t = new Thread();t.isInterrupted();即使是在main线程中,但线程t调用了isInterrupted方法,所以此线程就是指线程t

interrupted与isInterrupted方法的区别:interrupted方法是判断当前线程是否被中断,并清除中断状态,而isInterrupted方法是判断此线程是否被中断,不清除中断状态。

示例:

public class MyThread extends Thread {
    @Override
    public  void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("i="+(i+1));
        }
    }
}

public class Test{
	public static void main(String[] args ) {
		MyThread thread=new MyThread();
		thread.start();
		thread.interrupt();
		System.out.println("第一次调用thread.isInterrupted():"+thread.isInterrupted());
		System.out.println("第二次调用thread.isInterrupted():"+thread.isInterrupted());
        //测试interrupted()函数
		System.out.println("第一次调用thread.interrupted():"+thread.interrupted());
		System.out.println("第二次调用thread.interrupted():"+thread.interrupted());
		System.out.println("thread是否存活:"+thread.isAlive());
	}
}

测试结果如下所示:

thread线程调用了interrupt方法,并没有使thread线程立即中断,只是将thread线程的中断标志设置为true(线程的中断状态被设置),通过thread.isInterrupted方法判断线程的中断状态是否被设置,若被设置了,则返回true,否则返回false。从输出结果看,可能会有疑惑,为什么后面两个interrupted方法输出的都是false,而不是预料中的一个true一个false?注意!!!这是一个坑!!!上面说到,interrupted方法测试的是当前线程是否被中断,这里当前线程是main线程,而thread.interrupt中断的是thread线程,这里的此线程就是thread线程。所以当前线程main从未被中断过,尽管interrupted方法是以thread.interrupted的形式被调用,但它检测的仍然是main线程而不是检测thread线程,所以thread.interrupted在这里相当于main.interrupted。

若调用sleep()而使线程处于阻塞状态,这时调用interrupt()方法,会抛出InterruptedException,从而使线程提前结束阻塞状态,退出阻塞代码。为什么

1.默认blocker=null; ®1

2.调用方法“interrupt0();”将会导致该线程的中断状态将被设置(JDK文档中术语)”®2

3.再次调用“interrupt0();”将会导致其中断状态将被清除(JDK文档中术语)”®3

异常其实是interrupt()抛出的,而不是sleep()抛出的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值