java - Java中的线程间通信

标签 java multithreading junit java-memory-model

为什么在下面的 Java 代码中:

public class WaitForOther {

private volatile boolean in = false;// need volatile for transitive closure
                                    // to occur



public 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 导致缩短的输出:

准备好了! 放! 去吧!

否则会在中断的线程 0 中正确恢复:

Ready!
Set!
Go!
Resumed in Thread-0

这是调用上述行为的 JUnit 测试,正如评论中所要求的那样:

public class WaitForOtherTest {

    WaitForOther cut  = new WaitForOther();


    @Test
    public void testStoppingViaMonitorWait() throws Exception {
        cut.stoppingViaMonitorWait();
    }



}

谢谢!

最佳答案

我已经在 J​​Unit 中尝试过您的测试,但我得到的结果与您的体验相反:

  1. Thread.sleep 被注释掉时,测试运行正常并打印“Resumed in <>”
  2. Thread.sleep 在代码中(实际执行)时,JVM 终止并且“Resumed in ...”打印。

原因是 JUnit 在测试完成时终止了 VM。它执行 System.exit();。您很幸运在案例 1 中获得了完整的输出,因为它是在单独的线程中打印的,并且 JUnit 不会等待该线程。

如果要确保线程在测试方法结束之前完成,要么需要让 API 等待线程,要么需要让测试等待线程。

如果您的stoppingViaMonitorWait 方法返回它创建的线程,您可以在测试中等待。

@Test
public void testStoppingViaMonitorWait() throws Exception {
    Thread x = cut.stoppingViaMonitorWait();
    x.join();
}

另一种选择是将一个线程池(ExecutorService 的一个实例)注入(inject)到您正在测试的类中,让它在池中安排它的线程(这在任何情况下都更好),在您的测试方法中,您可以调用 ExecutorService.awaitTermination

关于java - Java中的线程间通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39322831/

相关文章:

JavaMail 保存密码

java - Android游戏java boolean 解决方案

Java 线程 - 等待所有子线程才能继续

c# - 优雅地终止由 QueueUserWorkItem() 分派(dispatch)的线程池任务

java - 如何编写可以与其他程序交互的程序

java - 从 HttpServletRequest 获取当前使用的协议(protocol)名称?

c# - 如何中止线程

java - JDBC 连接的 JUNIT 测试用例

java.lang.NoClassDefFoundError : org/hamcrest/SelfDescribing

java - Jenkins:监控 JUnit 测试执行时间?