java - 如果父线程较早完成,则子线程似乎无法完成

标签 java multithreading

我创建了一个 EventEmitter,它将事件传递给新线程中的监听器:

public class EventEmitter{

private Map<String,List<EventListener>> listeners = new HashMap<String,List<EventListener>>();
private Executor executor = Executors.newCachedThreadPool();

protected EventEmitter(Executor executor){
    this.executor = executor;
}

public void publish(Event e) {
    listeners.get(e.getClass().toString()).stream().forEach(listener->{
        executor.execute(()->{listener.beNotifiedOfEvent(e);});
    });
}

public void subscribe(EventListener listener,Class<?> eventClass) {

    assert Arrays.asList(eventClass.getInterfaces()).contains(Event.class);

    List<EventListener> listenersThatListenToIt = listeners.get(eventClass.toString());

    if(listenersThatListenToIt!=null){
        listenersThatListenToIt.add(listener);
    } else {
        listenersThatListenToIt = new ArrayList<EventListener>();
        listenersThatListenToIt.add(listener);
        listeners.put(eventClass.toString(),listenersThatListenToIt);
    }

}
}

我还在接收到事件的两秒后在监听器中打印一条消息:

@Component
public class StudentRegisteredEventListener implements EventListener {

@Override
public void beNotifiedOfEvent(Event e) {
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    StudentRegisteredEvent studentRegisteredEvent = (StudentRegisteredEvent) e;
    System.out.println("Received student registered event! Student's name is: "+studentRegisteredEvent.getRegisteredStudent());
}

}

我有以下 JUnit 测试:

    @Test
public void test_emitter_notifies_listener() {
    //given
    EventEmitter emitter = new CachedThreadPoolEventEmitter();
    //StudentRegisteredEvent event = new StudentRegisteredEvent();

    EventListener listener = Mockito.mock(StudentRegisteredEventListener.class);

    Student registeredStudent = new Student();
    registeredStudent.setName("studentName");

    //when
    emitter.subscribe(listener,StudentRegisteredEvent.class);
    emitter.publish(new StudentRegisteredEvent(registeredStudent));

    //then

    System.out.println("end of test");
}

我的问题是,当父线程在“beNotifiedOfEvent”调用结束之前结束时,不会打印来自监听器方法的行,所以我在控制台上只看到“测试结束”。

我感兴趣的是:这种行为的原因是什么,以及这是否会在测试环境之外起作用。我计划从 Spring MVC Controller 发布事件。这是否保证在父线程完成执行后完成?

最佳答案

不是线程终止而是整个过程。 JUnit kills the process when the test finishes ,所以即使是非守护线程也不能使 JUnit 测试进程保持 Activity 状态。(如果您仔细想想,这完全是直截了当的,没有人希望测试进程在完成实际测试后继续运行)。 In Java, threads do not have a hierarchy ,没有“父”线程这样的东西。然而,几乎每个应用程序都有某种“主”线程。 JUnit 有自己的主线程,在其中运行测试,最后调用 System.exit(0);

如果你想测试一些定时事件,你将不得不在测试用例中显式地等待线程。此外,我建议使用 ScheduledExecutorService而不是 Thread.sleep-s.

关于java - 如果父线程较早完成,则子线程似乎无法完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42260788/

相关文章:

c++ OpenMP每个循环中的多个线程

c - 将 Zed Shaw 的调试宏移植到 MSVC

java - 使用 GSON 序列化 ArrayList(通用类型)

java - 为什么 CyclicBarrier reset() 方法抛出 BrokenBarrierException

C++11 <thread> 使用 OpenGL 进行多线程渲染可防止主线程读取标准输入

multithreading - 将向量复制到线程

java - 你能解释一下这个 Java HashMap 键冲突吗?

java - 从 map 中获取数组并转换键

java - 正则表达式 Java 错误

java - Ant 通过 Jenkins : "BUILD SUCCESSFUL" in Console Output while build is still running