Reputation: 10122
If my thread receives an InterruptedException in a sleep(), how can I tell whether it was caused by a call on its .interrupt() or .notify() method?
The long story:
I have a View() class running in a thread. It should run worker(s) and update the view from time to time. It should also measure the time the worker took. The View() should be interruptable by the application (upon shutdown). The workers should wake up (notify) the thread during sleep when they have finished to measure the time they took. (Without notification, time measured would be rounded up to the next full sleep cycle which isn’t desired.) So an InterruptedException can be triggered by a call on the thread’s .interrupt() or .notify() method. How do I distinguish this inside the catch block?
public class View() implements Runnable {
Long started = null;
Long finished = null;
@Overload
public void run(){
Set<Thread> workers = new HashSet<Thread>();
for(int i = 1; i <= 5; i++){
Thread worker = new Thread(new Worker());
worker.start();
workers.add(worker);
}
started = System.getCurrentTimeMillis();
do{
try{
TimeUnit.SECONDS.sleep(3);
updateView();
}catch(InterruptedException e){
if(--> thread_was_notified <--){
finished = System.getCurrentTimeMillis();
updateView();
}
if(--> thread_was_notified <--){
for(Thread worker : workers)
worker.interrupt();
}
return;
}
}while(true);
}
protected void updateView(){
// …
}
}
I first guessed that InterruptedException would have Subclasses, but there are none directly known subclasses listet in the javadoc. Thread provides .isInterrupted()
, but as said here: “By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so.” So I can’t tell from .isInterrupted()
either. What’s the clean way to do it?
I have a vegue idea that my code should use Object.wait()
, but what’s the waiting object?
Upvotes: 0
Views: 438
Reputation: 304
The ugly solution:
Instead of having your Workers interrupting the View thread, put a method like this:
public void workedFinished() {
interruptedByWorker = true; // View attribute.
viewThread.interrupt(); // Interrupt the view
}
Then, when you're on your catch, check for the interruptedByWorker
boolean. If it is true, it was interrupted by a worker. Otherwise (make sure this is happens), it was interrupted by the shutdown.
The other solution Instead of interrupting the thread in two different places (which I think it could be confusing an error-prone), you could do the following:
1) Schedule a Runnable
to run every 3 seconds using a ScheduledExecutorService
to update the view.
2) Have a CountdownLatch
that is notified for each Worker that finishes. Please, notice that in your code, the first thread wakes up the View, meaning that the measured time will be only for that thread, it will not wait until the other threads finish.
Upvotes: 1
Reputation: 42005
InterruptedException
is only thrown when some thread interrupts you and not thrown when comming out of wait()
.
So when you are in sleep()
or wait()
and some other thread decides to interrupt you then Exception will be thrown.
When a thread is in wait()
state and notify() is called for it then it will again fetch the lock and resume its working without throwing any exception.
Upvotes: 0