我正在构建一个作为Spring MVC应用程序实现的插件。这个插件通过其中一个服务器上的gui部署在3到6个tomcat服务器上。插件的每个实例都有一个@Scheduled方法来收集服务器上的信息并将其存储在中央数据库中。
我的问题是卸载插件的gui界面会使一些@Scheduled线程运行。
例如,我有一个服务器1到3的环境。我通过服务器1上的gui安装并启用插件。现在有3个应用程序在服务器1 - 3上运行@Scheduled线程实例。如果我回到服务器1并卸载插件,线程在服务器1上可靠地被杀死,但服务器2或3没有被杀死。
我已实施以下内容,但行为仍然存在:
@Component
public class ContextClosedListener implements ApplicationListener<ContextClosedEvent> {
@Autowired
ThreadPoolTaskExecutor executor;
@Autowired
ThreadPoolTaskScheduler scheduler;
public void onApplicationEvent(ContextClosedEvent event) {
scheduler.shutdown();
executor.shutdown();
}
}
此外,我已经考虑将其实现为上下文侦听器而不是@Scheduled方法,但出于维护和可扩展性原因,我宁愿坚持使用Spring。
如何在这样的环境中可靠地杀死线程?
答案 0 :(得分:0)
我有几个想法。 ThreadPoolTaskExecutor有一个方法setThreadNamePrefix,它允许您设置线程的前缀。您可以将前缀设置为唯一的,然后在运行时查找并终止这些线程。您还可以在同一对象上使用setThreadGroup方法设置线程组,然后只停止线程组中的线程。
更好,更安全的解决方案是在预定作业中创建分组方法。这是停止Thread而不是调用Thread.stop()的旧“head in head”方法的首选方法。您可以通过设置公共前缀或使用如上所述的线程组来引用这些Runnables。
接下来的问题是:你如何轻松地停止线程?为此,它将取决于您的应用程序的实现方式。由于我主要处理Spring MVC应用程序,我的第一个解决方案是编写一个Controller来处理管理任务。如果这是JBoss,或其他一些拥有JMX的大型应用服务器(Tomcat可以配置为提供JMX,我相信,但我不认为它配置为开箱即用),我可能会编写一个支持JMX的bean来允许我通过应用服务器控制台停止线程。基本上,给自己一个方法来触发线程的停止。