如果我的线程在sleep()中收到InterruptedException,我如何判断它是否是由对.interrupt()或.notify()方法的调用引起的?
长篇故事:
我在一个线程中运行了一个View()类。它应该运行worker并不时更新视图。它还应该衡量工人的时间。 View()应该可以被应用程序中断(关闭时)。工作人员在完成测量他们服用的时间时,应该在睡眠期间唤醒(通知)线程。 (如果没有通知,测量的时间将四舍五入到下一个完整的睡眠周期,这是不希望的。)因此,可以通过调用线程的.interrupt()或.notify()方法来触发InterruptedException。我如何区分catch块?
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(){
// …
}
}
我首先猜测InterruptedException会有子类,但javadoc中没有直接知道的子类侦听。线程提供.isInterrupted()
,但是as said here:“按照惯例,任何通过抛出InterruptedException退出的方法都会在它执行时清除中断状态。”所以我无法从.isInterrupted()
判断出来。干净的方法是什么?
我有一个想法,我的代码应该使用Object.wait()
,但是等待对象是什么?
答案 0 :(得分:1)
丑陋的解决方案:
不要让您的Workers中断View线程,而是放置一个这样的方法:
public void workedFinished() {
interruptedByWorker = true; // View attribute.
viewThread.interrupt(); // Interrupt the view
}
然后,当你捕获时,检查interruptedByWorker
布尔值。如果是真的,那就被工人打断了。否则(确保发生这种情况),它被关闭中断。
其他解决方案 您可以执行以下操作,而不是在两个不同的地方中断线程(我认为这可能会使容易出错):
1)使用Runnable
安排ScheduledExecutorService
每3秒运行一次以更新视图。
2)为每个完成的工作人员通知CountdownLatch
。请注意,在您的代码中,第一个线程唤醒了View,这意味着测量的时间仅适用于该线程,它不会等到其他线程完成。
答案 1 :(得分:0)
InterruptedException
仅在某些线程中断您时被抛出,而在退出wait()
时不会抛出。
因此当你在sleep()
或wait()
并且其他一些线程决定打断你时,将抛出异常。
当一个线程处于wait()
状态并且为它调用notify()时,它将再次获取锁并恢复其工作而不会抛出任何异常。