Java thread interruption won't work for me (in groovy)

1k views Asked by At

Feeling stupid somehow as I'm now trying to get a simple interrupt for a thread working in groovy for some hours already.

Somehow following code won't set the 'interrupted' flag in the thread 'name'. Causing the loop to run 'til its end.

Found tons of other questions where usually the check for Thread.currentThread().isInterrupted() was missing. But this is not the case here:

def t = Thread.start('name') {
    try {
        for (int i = 0; i < 10 && !Thread.currentThread().isInterrupted(); ++i) {
            println "$i"
            sleep 1000
        }
    } catch (InterruptedException e) {
        println "Catched exception"
        Thread.currentThread().interrupt();
    }
}
println "Interrupting thread in 1..."
sleep 1000
println "Interrupting thread..."
t.interrupt()
sleep 2000

I get following output

Interrupting thread in 1...
0
Interrupting thread...
1
2
3
4
5
6
7
8
9

Wonder what I miss here / am doing wrong? Tried also using ExecutorService and calling cancel(true) on the returned Future. Didn't work either.

2

There are 2 answers

2
Vampire On BEST ANSWER

TL;DR: Do not use Thread interruption as abort criterion, but use some custom flag instead.


You are not using Thread.sleep() which would throw InterruptedException, but GDKs Object.sleep() which handles and ignores interruptions: http://docs.groovy-lang.org/docs/groovy-2.4.7/html/groovy-jdk/java/lang/Object.html#sleep(long)

Either use Thread.sleep() instead like: (interrupting in the catch block is useless in your case)

def t = Thread.start('name') {
    try {
        for (int i = 0; i < 10 && !Thread.interrupted(); ++i) {
            println i
            Thread.sleep 1000
        }
    } catch (InterruptedException e) {
        println "Catched exception"
    }
}
println "Interrupting thread in 1..."
sleep 1000
println "Interrupting thread..."
t.interrupt()

Or use the variant of Object.sleep() with a Closure and abort your loop in there, e. g. by throwing InterruptedException like:

def t
t = Thread.start('name') {
    try {
        for (int i = 0; i < 10 && !Thread.interrupted(); ++i) {
            println i
            sleep(1000) {
                throw new InterruptedException()
            }
        }
    } catch (InterruptedException e) {
        println "Catched exception"
    }
}
println "Interrupting thread in 1..."
sleep 1000
println "Interrupting thread..."
t.interrupt()

Having solved your confusion, now let me advice not to do what you are trying to do. Interrupting is any no way a good method for usage as abort condition. A sleep or blocking IO can always be interrupted due to various reasons. The much better approach is to make your run-loop check some boolean flag that you toggle to abort the work.

0
aventurin On

If you interrupt the thread while sleeping, the sleeping interrupted thread catches the InterruptedException thrown by Thread.sleep and the interrupted status is cleared. So your Thread.currentThread().isInterrupted() always returns false.

You can make your code work if you replace sleep 1000 with Thread.sleep(1000).