2

我正在构建一个作为 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。

我怎样才能在这样的环境中可靠地杀死线程?

4

1 回答 1

0

我有几个想法。ThreadPoolTask​​Executor 有一个方法 setThreadNamePrefix,它允许你设置线程的前缀。您可以将前缀设置为唯一的,然后在运行时查找并终止这些线程。您也可以使用同一对象上的 setThreadGroup 方法设置线程组,然后停止线程组中的线程。

更好、更安全的解决方案是在您计划的工作中创建一个突破方法。这是停止线程的首选方法,而不是调用 Thread.stop() 的旧“一枪打死”方法。您可以通过设置公共前缀或使用如上所述的线程组来获取对这些 Runnables 的引用。

下一个问题是:如何轻松停止线程?为此,这将取决于您的应用程序是如何实现的。由于我主要处理 Spring MVC 应用程序,我的第一个解决方案是编写一个控制器来处理管理任务。如果这是 JBoss,或者其他一些具有 JMX 的大型应用程序服务器(我相信 Tomcat 可以配置为提供 JMX,但我不认为它是开箱即用的),我可能会编写一个启用 JMX 的 bean 来允许我通过应用服务器控制台停止线程。基本上,给你自己一个触发线程停止的方法。

于 2013-01-23T20:23:41.520 回答