2014-07-17 60 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只会导致混淆。