8

我是并发和线程的新手——并且在工作中开发我的应用程序时一直在使用它们。本质上,我的 RMI 应用程序(服务器端组件)中有许多线程轮询文件中的更改(这些文件每隔几秒钟更新一次)。

在开发盒上进行测试时,我一直在从命令行运行服务器,然后在完成后手动关闭它,然后冲洗并全天重复。

正如它所发生的那样 - 我认为当我关闭命令行并继续处理时我的线程可能不会停止。这会导致一些非常糟糕的副作用——尽管我不是 100% 确定这是否可能,所以希望有人能证实这可能是这种情况。

如果我让一个线程成为守护进程——这是否意味着当我关闭命令行时——这些线程会自动停止?我需要一些很好地终止应用程序的方法,但是因为服务器最终将由 autosys 运行,所以我不确定关闭时让所有线程完成的最佳方法是什么

谢谢

4

3 回答 3

1

下面的代码演示了创建一个带有虚拟运行任务的线程池,然后启动该任务,当应用程序终止时,一个关闭挂钩运行,它取消所有正在运行的任务并干净地关闭线程池。

您不必像我一样使用 Callable,您可以使用 Runnables 和 threadPool.execute 方法并简单地终止线程池,这有点不那么优雅。

    final ExecutorService threadPool = Executors.newCachedThreadPool();
    final List<Future<Void>> runningTasks = new ArrayList<>();
    Future<Void> task = threadPool.submit(new Callable<Void>() {

        @Override
        public Void call() throws Exception {
            int count = 0;
            while(true) {
                System.out.println(++count);
                Thread.sleep(1000);
            }
        }
    });
    runningTasks.add(task);

    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            for(Future<Void> runningTask : runningTasks) {
                runningTask.cancel(true);
            }
            threadPool.shutdownNow();
        }
    });

关闭挂钩适用于独立应用程序。在 Java EE 容器中,您可以对 javax.servlet.ServletContextListener 执行相同的操作

于 2013-03-17T17:32:17.217 回答
1

线程在 Java 虚拟机中运行。如果停止 JVM,线程将不再运行。您可以看到退出 JVM 就像拔掉计算机的插头:什么都不能再运行了。

于 2013-03-17T17:32:29.793 回答
0

RMI 运行时创建您无法停止的线程。关闭服务的唯一方法是使用 System.exit()。

我在一个单独的线程中执行此操作。之后:new ShutThread().start(),关闭的线程等待 2 秒,让任何延迟消息有机会完成旅程,然后发出 System.exit()。

于 2013-03-17T17:40:29.953 回答