簡體   English   中英

如果父級先前完成,則子線程似乎無法完成

[英]Child thread seems not to complete if parent completes earlier

我創建了一個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控制器發布事件。 父線程完成執行后,這是否可以保證完成?

這不是線程終止而是整個過程。 測試完成后JUnit會終止進程 ,因此即使非守護進程線程也無法使JUnit測試進程保持活動狀態。 (如果你仔細想想,沒有人希望在完成實際測試后運行一個測試過程),這是非常簡單的。 在Java中,線程沒有層次結構 ,沒有“父”線程。 但是幾乎每個應用程序都有某種“主”線程。 JUnit有自己的主線程,在其中運行測試,並調用System.exit(0); 在末尾。

如果要測試某些定時事件,則必須在測試用例中明確地等待線程。 另外,我建議使用ScheduledExecutorService而不是Thread.sleep -s。

如果它在測試環境中不起作用,你不應該接受任何人的說法,它可能在測試環境之外工作。 首先讓您的測試正常工作。

如果您希望測試正常完成,那么您必須等待它產生的所有線程結束。 假設您的Executor實際上是ExecutorService ,則ExecutorService如下操作:

executorService.shutdown();
try 
{
    executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e) 
{
    ...
}

上面的代碼正在執行時,您的任務應該運行完成,因此您應該在任務結束之前看到顯示的消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM