在多线程应用程序中停止线程

3
我使用procrun创建了一个服务,通过反射启动特定的JAR文件。当服务启动时,它会启动一个线程,并在该线程中执行其余操作。然后每个插件加载自己的线程并在其中执行操作。
在服务停止期间,我调用了插件的stop方法。这些方法已经返回,我创建的任何线程都已终止。但即使在此之后,以下线程仍在运行。
        INFO: Thread No:0 = Timer-0
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:1 = WebSocketWorker-14
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:2 = WebSocketWorker-15
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:3 = WebSocketWorker-16
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:4 = WebSocketWorker-17
        Jan 13, 2016 10:49:58 AM com.kube.desktop.KubeSdkMain stop
        INFO: Thread No:5 = WebsocketSelector18
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:6 = AWT-EventQueue-0
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:7 = DestroyJavaVM
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop
        INFO: Thread No:8 = Thread-11
        Jan 13, 2016 10:49:58 AM com.test.desktop.SdkMain stop

以下是我打印这些线程的方式。
ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
        int noThreads = currentGroup.activeCount();
        Thread[] lstThreads = new Thread[noThreads];
        currentGroup.enumerate(lstThreads);
        for (int i = 0; i < noThreads; i++)
            LOGGER.log(Level.INFO, "Thread No:" + i + " = " + lstThreads[i].getName());

由于这些线程,当我停止服务时,它需要很长时间,然后超时。但是当我调用System.exit(0)时,服务能够快速停止。我该怎么做才能摆脱这些线程?当我通过反射启动JAR文件时,是否为每个插件创建了单独的线程?如果是,这些可能是它们吗?请给些建议。

有些插件在清理它们创建的内容时做得不够好,这只是粗糙的编程。 - ZhongYu
我已经使用ExecutorService创建了线程。所以我正在调用它的shutDown方法。我还通过一个布尔类型的volatile变量来确保这一点。 - AnOldSoul
我会先查看线程的运行情况 -- 使用jstack、kill -3、VisualVM或类似的工具获取线程转储。这可能会告诉您它们卡在了什么地方,从而告诉您如何解除卡住的状态。另外,您是如何创建执行器服务的? - yshavit
@ScaryWombat 哦,抱歉!我看错了你的评论。 - yshavit
@yshavit ExecutorService execService = Executors.newFixedThreadPool(10); 然后使用 execService.execute 来创建它们。 - AnOldSoul
显示剩余4条评论
1个回答

0

看起来插件本身正在启动线程(“INFO:Thread No:1 = WebSocketWorker-14” -> 套接字通常应该放在单独的线程中),如果您杀死启动线程,它们将不会被关闭。您必须强制执行插件在关闭时终止它们启动的所有线程,以确保它们不会留下任何东西。 “有些插件在清理所创建的内容方面做得不好。这只是粗心的编程。”- bayou.io在描述它真的很好。

调用System.exit()将仅杀死进程,这意味着它也将杀死进程创建的所有线程。

另一种方法是手动迭代所有运行中的线程,检查它是否为主线程,如果不是,则继续杀死它。您可以使用以下方法获取可迭代集合中的所有运行中的线程

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();

你可以使用以下代码获取当前正在运行的线程:

Thread currentThread = Thread.currentThread();

虽然这不是你想要的方式,但更多的是一种清理插件残留物的方式,而不是直接这样做。插件本身应该在禁用时负责关闭线程,但如果它们没有这样做,您可以使用上述方法手动清理。


我已经成功摆脱了我上面提到的1-5线程。如何关闭0、7和8线程?这些似乎是我无法控制的Java线程。 - AnOldSoul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接