Interrupt a sleeping thread without interrupting I/O

C

Chris

How do I interrupt a sleeping thread without interrupting any I/O that
it may be doing?

We've got a thread that reads data using an NIO channel, goes to sleep
for a minute, wakes up and reads some more, goes to sleep, etc.

I'd like to terminate the thread quickly, but gracefully. If it's
sleeping, I'd like to wake it up and have it exit; if it's reading data,
I want it to finish and then terminate.

The trouble is that if I call Thread.interrupt(), it will properly
interrupt a Thread.sleep(), but it will also interrupt a
FileChannel.read() operation with a ClosedByInterruptException. Ideally
I'd have a way to do only the former and not the latter.

Any ideas?
 
N

Nico

How do I interrupt a sleeping thread without interrupting any I/O that
it may be doing?

We've got a thread that reads data using an NIO channel, goes to sleep
for a minute, wakes up and reads some more, goes to sleep, etc.

I'd like to terminate the thread quickly, but gracefully. If it's
sleeping, I'd like to wake it up and have it exit; if it's reading data,
I want it to finish and then terminate.

The trouble is that if I call Thread.interrupt(), it will properly
interrupt a Thread.sleep(), but it will also interrupt a
FileChannel.read() operation with a ClosedByInterruptException. Ideally
I'd have a way to do only the former and not the latter.

Any ideas?

According to the javadoc, yes, the I/O will be interrupted.
You could set a boolean somewhere in a static field to know if the
thread is interruptible or not (doing IO or sleeping).
 
T

Tom Hawtin

Chris said:
The trouble is that if I call Thread.interrupt(), it will properly
interrupt a Thread.sleep(), but it will also interrupt a
FileChannel.read() operation with a ClosedByInterruptException. Ideally
I'd have a way to do only the former and not the latter.

Use wait and notify instead of interrupt.

If the thread may be in select, call wakeup.

Tom Hawtin
 
K

Knute Johnson

Chris said:
How do I interrupt a sleeping thread without interrupting any I/O that
it may be doing?

We've got a thread that reads data using an NIO channel, goes to sleep
for a minute, wakes up and reads some more, goes to sleep, etc.

I'd like to terminate the thread quickly, but gracefully. If it's
sleeping, I'd like to wake it up and have it exit; if it's reading data,
I want it to finish and then terminate.

The trouble is that if I call Thread.interrupt(), it will properly
interrupt a Thread.sleep(), but it will also interrupt a
FileChannel.read() operation with a ClosedByInterruptException. Ideally
I'd have a way to do only the former and not the latter.

Any ideas?

Synchronize the read and the interrupt.
 
T

Tom Hawtin

Knute said:
Chris wrote:
Synchronize the read and the interrupt.

That still leaves a race condition. Consider the I/O thread is leaving
the sleep and is about to acquire the lock. Meanwhile the interrupting
thread acquires the lock and interrupts. End result is that the
interrupt occurs in the first I/O operation.

A refinement is to check and clear the interrupt status between locking
and I/O, but a standard wait-notify should suffice.

Tom Hawtin
 
K

Knute Johnson

Tom said:
That still leaves a race condition. Consider the I/O thread is leaving
the sleep and is about to acquire the lock. Meanwhile the interrupting
thread acquires the lock and interrupts. End result is that the
interrupt occurs in the first I/O operation.

A refinement is to check and clear the interrupt status between locking
and I/O, but a standard wait-notify should suffice.

Tom Hawtin

Tom:

How would you implement that with wait/notify?
 
T

Tom Hawtin

How would you implement that with wait/notify?

In the I/O thread:

for (;;) {
performIO();
synchronized (lock) {
if (exit) {
return;
}

lock.wait(delay);

if (exit) {
return;
}
}
}

In interrupting thread:

public void stopIOThread() {
synchronized (lock) {
exit = true;
lock.notifyAll();
}
}

Tom Hawtin
 
C

Chris

Tom said:
In the I/O thread:

for (;;) {
performIO();
synchronized (lock) {
if (exit) {
return;
}

lock.wait(delay);

if (exit) {
return;
}
}
}

In interrupting thread:

public void stopIOThread() {
synchronized (lock) {
exit = true;
lock.notifyAll();
}
}

Tom Hawtin

I'm confused. Suppose I/O thread is currently waiting, sitting in the
synchronized{} block. The interrupting thread tries to call
stopIOThread(). Wouldn't it just hang, waiting to get into the
synchronized{} block? It would never get a chance to call notifyAll()
until I/O thread had timed out.
 
T

Tom Hawtin

Chris said:
I'm confused. Suppose I/O thread is currently waiting, sitting in the
synchronized{} block. The interrupting thread tries to call
stopIOThread(). Wouldn't it just hang, waiting to get into the
synchronized{} block? It would never get a chance to call notifyAll()
until I/O thread had timed out.

No. Wouldn't be much point in calling notifyAll ever if that were the case.

From the API docs for Object.wait():

"The thread releases ownership of this monitor and waits until
another thread notifies threads waiting on this object's monitor to wake
up either through a call to the notify method or the notifyAll method."

Tom Hawtin
 
C

Chris

Tom said:
No. Wouldn't be much point in calling notifyAll ever if that were the case.

From the API docs for Object.wait():

"The thread releases ownership of this monitor and waits until another
thread notifies threads waiting on this object's monitor to wake up
either through a call to the notify method or the notifyAll method."

Aha! Thanks. I just tried it and it worked perfectly. This solves the
problem.
 
K

Knute Johnson

Tom said:
In the I/O thread:

for (;;) {
performIO();
synchronized (lock) {
if (exit) {
return;
}

lock.wait(delay);

if (exit) {
return;
}
}
}

In interrupting thread:

public void stopIOThread() {
synchronized (lock) {
exit = true;
lock.notifyAll();
}
}

Tom Hawtin

Thanks Tom, sorry I was so slow responding.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top