与java中线程状态相关的interrupt()方法的精确行为

Posted

技术标签:

【中文标题】与java中线程状态相关的interrupt()方法的精确行为【英文标题】:precise behaviour of interrupt() method with respective to thread states in java 【发布时间】:2016-10-27 20:04:30 【问题描述】:

我已经阅读了下面的帖子

What does java.lang.Thread.interrupt() do? 但我没能完全正确

我引用@Mike_q 对上述问题的回答如下

Thread.interrupt() 设置目标线程的中断状态/标志。然后在该目标线程中运行的代码可以轮询中断状态并适当地处理它。一些阻塞的方法如 Object.wait() 可能会立即消耗中断状态并抛出适当的异常(通常是 InterruptedException)

它说当对象处于 WAITING 时它可以消耗中断状态,那么当它处于 BLOCKED 状态等待对象的锁定时会发生什么......?

我已经在下面尝试了这种情况,代码是

在 X:t2 被阻止

    public class interruptsyc

    static Object resource = new Object();
    public static void main(String []args)
    
        System.out.println("started main");
        Thread1 t1=new Thread1("thread 1");
        t1.start();
        delay(1000);
        Thread2 t2 =new Thread2("thread 2");
        t2.start();
        delay(1000);
        t2.interrupt(); // X: at this point t2 is in blocked state waiting for resource's lock
        System.out.println(t2.getName()+t2.interrupted());
        delay(1000);
        System.out.println("end main");

    
    static void delay(long n)
    
        try
        
        Thread.sleep(n);
        
        catch(InterruptedException ex)
        
            System.out.println(Thread.currentThread().getName()+Thread.interrupted());
            ex.printStackTrace();
        
    
    static class Thread1 extends Thread

        Thread1(String name)
        
            setName(name);
        
        public void run()
        
            synchronized(resource)
            
                System.out.println("start 1");
                delay(6000);
                System.out.println("end 1");
            
        
    
    static class Thread2 extends Thread
        Thread2(String name )
        
        setName(name);  
        
        public void run()
        
            synchronized(resource)
            
                System.out.println("start 2");
                delay(2000);
                System.out.println("end 2");
            
        
    

输出低于

started main
start 1
false
end main
end 1
start 2
thread 2false
java.lang.InterruptedException: sleep interrupted
        at java.lang.Thread.sleep(Native Method)
        at interruptsyc.delay(interruptsyc.java:25)
        at interruptsyc$Thread2.run(interruptsyc.java:59)
end 2

好像调用了InterruptedException,后面调用sleep方法的时候……这是为什么……?

再一次,我从这里所说的内容中不太明白什么是轮询

通过 Thread.interrupted() 方法进行轮询,该方法返回当前线程的中断状态并清除该中断标志。通常线程可能会做一些事情,比如抛出 InterruptedException。

每当我在上面的代码中调用 Thread2.interrupted() 方法时,它都会返回 false (当我在 t2.interrupt 之后和 catch 块中调用时)

【问题讨论】:

【参考方案1】:

好像调用了InterruptedException,后面调用sleep方法的时候……这是为什么……?

因为阻塞/休眠方法不会立即阻塞。他们首先检查线程是否被中断,如果已经被中断,则立即抛出 InterruptedException,以便线程尽快停止。

每当我在上面的代码中调用 Thread2.interrupted() 方法时,它都会返回 false

因为当阻塞/休眠方法抛出 InterruptedException 时,它们也会清除中断标志。

这是在Thread.sleep()的javadoc中:

抛出 InterruptedException - 如果任何线程中断了当前线程。抛出该异常时清除当前线程的中断状态。

【讨论】:

但是上面代码中的t2.interrupt()此时还没有抛出中断异常并且中断标志仍然有效 不知道你在问什么,但我认为你对t2.interrupted() 的电话引起了一些混乱。 ìinterrupted() 是一个静态 方法。它检查当前线程是否被中断。所以你不应该把它叫做t2.interrupted(),而应该叫做Thread.interrupted()。要知道在另一个线程被中断,无需清除中断标志,使用t2.isInterrupted()。我重写了您的代码以产生更有意义的输出:gist.github.com/jnizet/1e983582a5f5d8b1e9b6a81ed2a731e9

以上是关于与java中线程状态相关的interrupt()方法的精确行为的主要内容,如果未能解决你的问题,请参考以下文章

正确的使用interrupt停止线程

谈谈 Java 线程状态相关的几个方法

关于Java多线程-interrupt()interrupted()isInterrupted()解释

Java中的中断(Interrupt)

Java并发编程-如何终止线程

java 多线程之取消与关闭