为什么在以下Java代码中:public class WaitForOther {private volatile boolean in = false;// need volatile for transitive closure // to occurpublic void stoppingViaMonitorWait() throws Exception { final Object monitor = new Object(); new Thread(new Runnable() { @Override public void run() { synchronized (monitor) { in = true; try { monitor.wait(); // this releases monitor //Thread.sleep(8000); //No-op System.out.println("Resumed in " + Thread.currentThread().getName()); } catch (InterruptedException ignore) {/**/ } } } }).start(); System.out.println("Ready!"); while (!in); // spin lock / busy waiting System.out.println("Set!"); synchronized (monitor) { System.out.println("Go!"); monitor.notifyAll(); }}Thread.sleep(8000); //No-op的取消注释会导致输出缩短:Ready! Set! Go!否则可以在中断的Thread-0中正确恢复:Ready!Set!Go!Resumed in Thread-0这是JUnit测试,它会按照注释中的要求调用上述行为:public class WaitForOtherTest { WaitForOther cut = new WaitForOther(); @Test public void testStoppingViaMonitorWait() throws Exception { cut.stoppingViaMonitorWait(); }}谢谢! 最佳答案 我已经在JUnit中尝试了您的测试,但与您所经历的相反:当Thread.sleep被注释掉时,测试运行正常,并显示“在中恢复”当代码中的Thread.sleep(实际执行)时,JVM终止,并且不打印“ Resumed in ...”。原因是测试完成后,JUnit会终止VM。它执行System.exit();。您很幸运在第一种情况下获得了完整的输出,因为它是在单独的线程中打印的,并且JUnit不在等待该线程。如果要确保在测试方法结束之前完成线程,则需要让API等待线程,或者需要使测试等待线程。如果您的stoppingViaMonitorWait方法返回它创建的线程,则可以在测试中等待。@Testpublic void testStoppingViaMonitorWait() throws Exception { Thread x = cut.stoppingViaMonitorWait(); x.join();}另一种选择是,将线程池(ExecutorService的实例)注入到要测试的类中,让其将线程安排在该池中(无论如何更好),然后在测试方法中可以调用ExecutorService.awaitTermination。
07-24 09:46
查看更多