Issue
the following short sample code illustrated the behavior that I couldn't explain
ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();
Thread t = new Thread(() -> {
long cnt = 0;
try {
while(!Thread.currentThread().isInterrupted()) {
testQueue.add(Math.random());
cnt++;
try {
Thread.sleep(100);
}catch (Exception e) {
System.out.println(String.format("inner interrupted inserted %d record", cnt));
}
}
} catch (Exception e) {
System.out.println(String.format("interrupted inserted %d record", cnt));
}
System.out.println(String.format("inserted %d record", cnt));
});
If I called t.interrupt()
to interrupt the thread
the expected behavior is 2 printed line that says:
inner interrupted inserted %d record
inserted %d record
where %d is replaced with corresponding value.
but the actual result is
inner interrupted inserted %d record
if we remove the inner catch to the Thread
ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();
Thread t = new Thread(() -> {
long cnt = 0;
try {
while(!Thread.currentThread().isInterrupted()) {
testQueue.add(Math.random());
cnt++;
Thread.sleep(100);
}
} catch (Exception e) {
System.out.println(String.format("interrupted inserted %d record", cnt));
}
System.out.println(String.format("inserted %d record", cnt));
});
then we get the output
interrupted inserted %d record
inserted %d record
as expected, as now the outer catch is catching the InterruptException
However, if instead I placed break in the inner most catch of the first code sample like so:
ConcurrentLinkedDeque<Double> testQueue = new ConcurrentLinkedDeque<>();
Thread t = new Thread(() -> {
long cnt = 0;
try {
while(!Thread.currentThread().isInterrupted()) {
testQueue.add(Math.random());
cnt++;
try {
Thread.sleep(100);
}catch (Exception e) {
System.out.println(String.format("inner interrupted inserted %d record", cnt));
break; //this one
}
}
} catch (Exception e) {
System.out.println(String.format("interrupted inserted %d record", cnt));
}
System.out.println(String.format("inserted %d record", cnt));
});
the expected behavior is produced.
why would the placement of the catch block create such difference?
Solution
See the documentation for Thread#interrupt
:
If this thread is blocked in an invocation of [...] sleep(long), or sleep(long, int), [...], then its interrupt status will be cleared and it will receive an InterruptedException.
If none of the previous conditions hold then this thread's interrupt status will be set.
That means that in your examples either Thread#sleep
throws the exception XOR Thread.currentThread().isInterrupted()
gives you true.
So in your first example you catch the exception, do the print and enter/stay in the infinite loop as Thread.currentThread().isInterrupted()
is always false
.
In your second example the try-catch is not nested within the loop, so both prints happen and the thread terminates as expected.
In your third example you just explicitly exit the loop.
FYI: You don't neet to write System.out.println(String.format(...))
. There is System.out.printf
, but don't forget the \n
.
Answered By - akuzminykh
Answer Checked By - Mildred Charles (JavaFixing Admin)