[英]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.