如果我的线程在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(),但是等待对象是什么?

最佳答案

丑陋的解决方案:

而不是让您的Workers中断View线程,而是放置一个这样的方法:

public void workedFinished() {
  interruptedByWorker = true; // View attribute.
  viewThread.interrupt(); // Interrupt the view
}


然后,当您遇到问题时,请检查interruptedByWorker布尔值。如果属实,则被工人打断。否则(请确保发生这种情况),它已被关机中断。

另一种解决方案
您可以执行以下操作,而不是在两个不同的地方中断线程(我认为这可能会使容易出错的地方造成混乱),

1)使用Runnable安排ScheduledExecutorService每3秒运行一次以更新视图。
2)有一个CountdownLatch通知每个完成的Worker。请注意,在您的代码中,第一个线程将唤醒View,这意味着所测量的时间将仅针对该线程,而不会等到其他线程完成。

10-08 02:24