4

我正在尝试构造两个线程,线程A是主线程,线程B是第二个线程,线程B正在通过一个耗时的函数更新一个变量(这个变量应该在两个线程之间共享,因为最终线程A需要使用该变量也是如此),但是如果线程 B 完成时间过长(使用异常),我希望线程 A 终止线程 B。

我尝试的是以下内容:

Thread thread = new Thread() {
     public void run() {
         /// run something that could take a long time
     }
};

synchronized (thread) {
    thread.start();
}

System.err.println("Waiting for thread and terminating it if it did not stop.");
try {
   thread.wait(10000);
} catch (InterruptedException e) {
   System.err.println("interrupted.");
}

如果行为运行超过 10 秒,是否应该给出终止行为的预期行为?线程对象在等待后被删除,因为运行线程的方法返回。

现在,这段代码发生的事情是我总是在 wait(10000) 命令上得到 java.lang.IllegalMonitorStateException。

4

2 回答 2

3

IllegalMonitorStateException如果你调用wait()一个你不在的对象,你总是会得到一个synchronized

try {
    // you need this to do the wait
    synchronized (thread) {
       thread.wait(10000);
    }
} catch (InterruptedException e) {
    System.err.println("interrupted.");
}

如果您正在等待thread完成,那么您可能正在尝试执行以下操作:

try {
    thread.join(10000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    System.err.println("interrupted.");
}

不幸的是,此时您不知道线程是否正在运行,因为join无论它是否超时(抱怨)都不会返回。因此,您需要thread.isAlive()在加入后测试是否。

如果您问如何取消thread如果它运行的时间超过10000毫秒,那么正确的做法是使用thread.interrupt(). 这将导致任何sleep()wait()方法抛出一个InterruptedException,并将在线程上设置中断标志。

要使用中断标志,您的线程应该执行以下操作:

   while (!Thread.currentThread.isInterrupted()) {
       // do it's thread stuff
   }

此外,执行以下操作始终是一个很好的模式,因为一旦InterruptedException抛出 ,中断标志就被清除了:

} catch (InterruptedException e) {
    // set the interrupt flag again because InterruptedException clears it
    Thread.currentThread.interrupt();
    System.err.println("interrupted.");
}
于 2012-04-28T00:12:41.173 回答
1

该代码不正确。方法waitObject类中声明,旨在暂停当前线程,并将其用作调用它的对象的监视器实例。您只能在synchronized部分中调用此方法,这就是您得到异常的原因。

关于你的问题:一般来说,如果它不想停止,你不能停止另一个线程。因此,您应该调用Thread.interrupt以通知线程它应该停止工作,并且由该线程决定是否考虑该通知。要检查线程是否被中断,您可以使用interrupted()orisInterrupted()方法。

于 2012-04-28T00:14:21.063 回答