在我的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();
}
}
但是当我停止服务器时,线程继续在后台运行。我无法控制执行器,有办法停止线程吗?
在ExecutorService
上调用shutdown
或shutdownNow
不会停止当前正在执行任务的线程。shutdownNow
将等待所有当前正在执行的任务完成。强制停止线程是一件非常糟糕的事情,任何行为良好的Java代码都不会这样做。
如果你想要停止线程,那么你需要传递某种类型的信号给线程,然后你的代码需要读取该信号。ExecutorService#shutdownNow
为你完成了一半的工作——它向当前正在执行的线程发送一个中断信号。您的代码有中断处理的开始,但它没有正确实现。
当您得到InterruptedException
时,您不能只是记录它并继续-该异常告诉您线程已被中断,它需要完成它正在做的事情并退出(参见Java理论与实践:处理InterruptedException -一篇非常值得新手和专家阅读的优秀文章)。而不是记录一个错误,当你得到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
,它应该实现Runnable
。ExecutorService
将其视为Runnable
,因为Thread
碰巧实现了该接口,但ExecutorService
创建并管理自己的线程。自己扩展Thread
只会导致混乱。