LinkedBlockingQueue.poll(...)偶尔抛出InterruptedException

时间:2018-04-04 22:54:34

标签: java multithreading

我使用的是java 1.8 java.util.concurrent.LinkedBlockingQueue,当我打电话时:

LinkedBlockingQueue.poll(5000, TimeUnit.MILLISECONDS)

偶尔会抛出InterruptedException

java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2014)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2088)
    at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)

我认为正在发生这种情况,因为以下内容在checkInterruptWhileWaiting() at AbstractQueuedSynchronizer:2079

的(间接)调用期间返回true
Unsafe.compareAndSwapInt(...) 

作为旁注,Unsafe.compareAndSwapInt会返回boolean,但boolean是什么意思?我无法找到关于该类/功能的任何文档。

我怀疑另一个线程中发生的事情导致了这个问题,但我不知道现在该去哪里看。

任何帮助理解InterruptedException被抛出的原因都会非常有帮助。我真的希望能够在一个小的测试程序中重现它,但它现在处于一个大乱的程序中,所以我试图理解可能导致这种情况的因素,以便我可以创建一个测试程序来重现它。

1 个答案:

答案 0 :(得分:0)

您的应用中是否有其他线程调用Thread.interrupt()?这就是awaitInNanos()

中发生的事情
if (Thread.interrupted())
            throw new InterruptedException();

如果你控制线程,那么你可以覆盖interrupt方法仅用于测试

    Thread thread = new Thread() {
        @Override
        public void run() {
            // do something longrunning
        }

        @Override
        public void interrupt() {
            // try-finally ensures to run both super.interrupt() and the deubg code 
            try {
                super.interrupt();
            } finally {
                // you can use any logging services that you already have
                System.out.println("--> Interrupted from thread: " + Thread.currentThread().getName());
                Thread.dumpStack();
            }
        }
    };

如果手动创建线程,则可以覆盖interrupt()。如果您使用执行程序,那么您可以提供ThreadFactory,使用正确的interrupt()方法创建线程。

这是一个使用此调试技术的main()方法。请注意,您需要在STDIN中输入一行或手动终止该过程。否则它将永远运行(jvm restart)。

public static void main(String[] args) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            System.out.println("--> asdf");
            try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
                br.readLine();
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }

        }

        @Override
        public void interrupt() {
            // try-finally ensures to run both super.interrupt() and the deubg code 
            try {
                super.interrupt();
            } finally {
                // you can use any logging services that you already have
                System.out.println("--> Interrupted from thread: " + Thread.currentThread().getName());
                Thread.dumpStack();
            }
        }
    };
    thread.start();
    System.out.println("--> before interrupt");
    thread.interrupt();
    System.out.println("--> after interrupt");
}