在我的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();
}
}
但是当我停止服务器时,线程继续在后台运行。我无法控制执行程序,有没有办法停止线程?
答案 0 :(得分:2)
在shutdown
上调用shutdownNow
或ExecutorService
不会停止当前正在执行任务的线程。 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
,它应该只实现Runnable
。 ExecutorService
将其视为Runnable
,因为Thread
碰巧实现了该接口,但ExecutorService
创建并管理自己的线程。自己扩展Thread
只会导致混乱。