Reputation: 21
I'm using a java 1.8 java.util.concurrent.LinkedBlockingQueue
, and when I call:
LinkedBlockingQueue.poll(5000, TimeUnit.MILLISECONDS)
it is very occasionally throwing an 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)
which I think is happening because the following is returning true during the (indirect) call to checkInterruptWhileWaiting() at AbstractQueuedSynchronizer:2079
Unsafe.compareAndSwapInt(...)
As a side note, Unsafe.compareAndSwapInt
returns a boolean
, but what does that boolean
mean? I can't find any documentation on that Class/function.
I suspect that something is going on in another thread to cause this issue, but I'm not sure where to look right now.
Any help on understanding why the InterruptedException
is being thrown would be very helpful. I would really like to be able to reproduce it in a small test program, but it's in a big messy program right now so I'm trying to understand what things could cause this so that I can create a test program to reproduce it.
Upvotes: 2
Views: 1225
Reputation: 7166
Is there any other thread in your app that calls Thread.interrupt()
? This is what's happening in awaitInNanos()
:
if (Thread.interrupted())
throw new InterruptedException();
If you control the threads, then you can override the interrupt
method just for testing:
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();
}
}
};
If you create the threads manually, you can override interrupt()
. If you use executors, then you can provide a ThreadFactory
, that creates the threads with the right interrupt()
method.
Here is a main()
method that plays with this debug technique. Please note that you need to enter a line in STDIN
or manually kill the process. Otherwise it's going to run forever (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");
}
Upvotes: 1