等待方法期间抛出中断异常的时间

4
在Object类的JavaDoc中,wait(long timeout)方法描述如下:
“如果当前线程在等待之前或等待时被任何线程中断,则会抛出InterruptedException异常。”
上述语句中的“before”是指在执行obj.wait()之前,即在其上面定义的任何指令执行之前。
synchronized (obj) {
         while (<condition does not hold>)
             obj.wait(timeout);
         ... // Perform action appropriate to condition
     }

可能是因为wait(timeout)检查线程是否已启动。如果没有启动,则会抛出异常。 - mubeen
这个“obj”是什么?它是线程对象吗? - mubeen
obj 可以是任何对象。 - Pushparaj
2个回答

3
在上述语句中,“before”是什么意思?在执行obj.wait()之前是指在其上方定义的任何指令之前吗?
这意味着,如果线程在调用wait()方法之前被中断,那么当实际调用wait()方法时,仍会抛出InterruptedException异常。
为了尝试这种情况,我编写了以下代码来启动线程并中断它。此线程的run()方法循环INTEGER.MAX_VALE-1次,并调用wait()方法。在到达调用wait()方法的时候,线程已经被中断。随后,在调用wait()方法时,它抛出了InterruptedException异常。
public class ThreadWaitInterruption {
    static Object obj = new Object();
    
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Started Thread");
                for(int i = 0; i < Integer.MAX_VALUE; i++) {
                    int j = i/2;
                }
                
                System.out.println("Loop completed");
                
                synchronized (obj) {
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.start();
        System.out.println("Interrupting");
        t.interrupt();
        System.out.println("Interuupted");
    }
}

样例输出,使用1.8 Java热点(TM) 64位版本测试。

Interrupting
Started Thread
Interuupted
Loop completed
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.demo.threads.ThreadWaitInterruption$1.run(ThreadWaitInterruption.java:19)
    at java.lang.Thread.run(Thread.java:745)

或者

Started Thread
Interrupting
Interuupted
Loop completed
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.demo.threads.ThreadWaitInterruption$1.run(ThreadWaitInterruption.java:19)
    at java.lang.Thread.run(Thread.java:745)

在中断线程之前调用wait()方法,即使线程在调用wait()方法之前被中断,调用wait()方法也会导致抛出InterruptedException异常。

注意:由于这是一个多线程程序,以上输出的顺序不能保证,我们可能需要运行此程序几次才能得到上述确切的输出。


我建议你在run方法之外定义Object obj(可以将其作为字段)。即使你正在说明其他内容,也没有必要在局部变量上同步。 - Kedar Mhaswade
@KedarMhaswade 这是个好建议,已经加入了。现在将其设为 ThreadWaitInterruption 类中的一个静态字段。 - Madhusudana Reddy Sunnapu

1

调用Thread#interrupt仅会在线程上设置中断标志,要使中断起作用,需要被中断的线程的配合。被中断的任务需要执行以下操作之一:

  • 检查中断标志(使用Thread.currentThread()。isInterrupted())或

  • 执行可能引发InterruptedException的操作(等待/睡眠/加入等)

才能使中断产生任何效果。

像wait或sleep这样的方法基于它们检测到正在调用线程中当前设置了中断标志而抛出InterruptedException。中断标志可能已在进入方法之前设置。

如果您有嵌套的线程安全组件,其中包含等待、睡眠或加入,则当一个组件接收到中断时,它可以让InterruptedException被抛出,也可以捕获异常并恢复中断标志(该标志在抛出异常时被清除)。这样,由该线程遍历的组件中的所有部分都可以意识到挂起的取消,并以响应的方式终止其正在进行的操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接