在Spring中停止一个线程

时间:2014-07-17 10:11:28

标签: multithreading spring executorservice executor

在我的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();
    }
}

但是当我停止服务器时,线程继续在后台运行。我无法控制执行程序,有没有办法停止线程?

1 个答案:

答案 0 :(得分:2)

shutdown上调用shutdownNowExecutorService不会停止当前正在执行任务的线程。 shutdownNow将等待所有当前正在执行的任务完成。强行停止线程是一件非常糟糕的事情,没有表现良好的Java代码会这样做。

如果你想停止你的线程,那么你需要向线程传递某种信号,然后你的代码需要读取该信号。 ExecutorService#shutdownNow为你做了一半 - 它向当前正在执行的线程发送一个中断信号。您的代码具有中断处理的开始,但它没有正确实现。

当你得到InterruptedException时,你不能只记录它并继续前进 - 该异常告诉你你的线程已被中断,它需要完成它正在做的事情并退出(见{{ 3}} - 一篇非常值得新手和专家阅读的文章。获取InterruptedException后,您的代码需要退出该方法(例如,使用return),而不是记录错误。

在while循环中,您需要检查线程是否已被中断,如果已经中断则退出。所以你的run方法现在变成这样:

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只会导致混乱。