2014-07-17 97 views
1

在我的Spring應用程序中,我啓動了一個像這樣的線程。在春天停止線程

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.ApplicationListener; 
import org.springframework.context.event.ContextRefreshedEvent; 
import org.springframework.context.event.ContextStoppedEvent; 
import org.springframework.stereotype.Component; 

@Component 
public class RunBackgroundServices implements ApplicationListener<ContextRefreshedEvent> { 

    private final BackgroundServices backgroundServices; 

    private ExecutorService executor; 

    @Autowired 
    public RunBackgroundServices(BackgroundServices backgroundServices) { 
     this.backgroundServices= backgroundServices; 
    } 

    @Override 
    public void onApplicationEvent(ContextRefreshedEvent event) { 

     executor = Executors.newSingleThreadExecutor(); 
     executor.submit(backgroundServices); 
    } 

    public void onApplicationEvent(ContextStoppedEvent event) { 
     backgroundServices.close(); 
     executor.shutdownNow(); 
    } 
} 

這是線程BackGroundServices。

public class BackgroundServices extends Thread { 

    @Autowired 
    HL7Listener hL7Listener; 

    @Autowired 
    HISListener hISListener; 

    @Autowired 
    PollHIS pollHIS; 

    @Autowired 
    PollPatientPortal pollPatientPortal; 

    private static final Logger logger = LoggerFactory.getLogger(BackgroundServices.class); 

    public void run() { 
     logger.debug("BackgroundServices :: run"); 
     try { 
      hL7Listener.start(); 
     } catch (InterruptedException e) { 
      logger.error(e.getStackTrace().toString()); 
     } 

     try { 
      hISListener.start(); 
     } catch (InterruptedException e) { 
      logger.error(e.getStackTrace().toString()); 
     } 

     while (true) { 
      pollHIS.start(); 
      pollPatientPortal.start(); 
     } 
    } 

    public void close(){ 
     hL7Listener.stop(); 
     hISListener.stop(); 
    } 
} 

但是當我停止服務器時,線程繼續在後臺運行。我無法控制執行者,是否有辦法阻止該線程?

回答

2

ExecutorService上調用shutdownshutdownNow不會停止當前正在執行任務的線程。 shutdownNow將等待所有當前正在執行的任務完成。強制停止線程是一件非常糟糕的事情,沒有行爲良好的Java代碼可以做到這一點。

如果你想停止你的線程,那麼你需要傳遞某種信號給線程,然後你的代碼需要讀取這個信號。 ExecutorService#shutdownNow爲你做了一半 - 它發送一箇中斷信號給當前正在執行的線程。你的代碼有中斷處理的開始,但沒有正確實現。

當你得到一個InterruptedException,你不能只是記錄它,繼續前進 - 該異常是告訴你,你的線程已經中斷,它需要完成它在做什麼和退出(見Java theory and practice: Dealing with InterruptedException - 一個極好的文章新手和專家都值得一讀)。代碼InterruptedException不是記錄錯誤,而是代碼需要退出該方法(例如,使用return)。

在你的while循環中,你需要檢查線程是否被中斷,如果有,就退出。所以,你的運行方法,現在就變成這樣的:

public void run() { 
    logger.debug("BackgroundServices :: run"); 
    try { 
     hL7Listener.start(); 
     hISListener.start(); 
    } catch (InterruptedException e) { 
     logger.error(e.getStackTrace().toString()); 
     return; 
    } 

    while (true) { 
     if (Thread.currentThread.isInterrupted()) { 
      logger.debug("Thread interrupted, exiting"); 
      return; 
     } 
     pollHIS.start(); 
     pollPatientPortal.start(); 
    } 
} 

最後一件事 - BackgroundServices不應擴大Thread,它應該只是實施RunnableExecutorService將其視爲Runnable,因爲Thread恰好實現該接口,但ExecutorService創建並管理其自己的線程。自己擴展Thread只會導致混淆。