java - 优雅地关闭线程和执行器

标签 java multithreading

以下代码尝试完成此操作。

代码永远循环并检查是否有任何待处理的请求需要处理。如果有,它会创建一个新线程来处理请求并将其提交给执行程序。一旦所有线程都完成,它会 hibernate 60 秒并再次检查待处理的请求。

public static void main(String a[]){
    //variables init code omitted
    ExecutorService service = Executors.newFixedThreadPool(15);
    ExecutorCompletionService<Long> comp = new ExecutorCompletionService<Long>(service);
    while(true){
        List<AppRequest> pending = service.findPendingRequests();
        int noPending = pending.size();
        if (noPending > 0) {
            for (AppRequest req : pending) {
                Callable<Long> worker = new RequestThread(something, req);
                comp.submit(worker);
            }
        }
        for (int i = 0; i < noPending; i++) {
            try {
                Future<Long> f = comp.take();
                long name;
                try {
                    name = f.get();
                    LOGGER.debug(name + " got completed");
                } catch (ExecutionException e) {
                    LOGGER.error(e.toString());
                }
            } catch (InterruptedException e) {
                LOGGER.error(e.toString());
            }
        }
        TimeUnit.SECONDS.sleep(60);
    }

  }

我的问题是这些线程完成的大部分处理都与数据库有关。这个程序将在 Windows 机器上运行。当有人试图关闭或注销机器时,这些线程会发生什么?如何优雅地关闭正在运行的线程和执行器。?

最佳答案

ExecutorService 的典型有序关闭可能如下所示:

final ExecutorService executor;

Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
        executor.shutdown();
        if (!executor.awaitTermination(SHUTDOWN_TIME)) { //optional *
            Logger.log("Executor did not terminate in the specified time."); //optional *
            List<Runnable> droppedTasks = executor.shutdownNow(); //optional **
            Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed."); //optional **
        }
    }
});

*您可以记录执行者在等待您愿意等待的时间后仍有任务要处理。
**您可以尝试强制执行器的工作线程放弃其当前任务并确保它们不会启动任何剩余的任务。

请注意,当用户向您的 java 进程发出中断或您的 ExecutorService 仅包含守护线程时,上述解决方案将起作用。相反,如果 ExecutorService 包含尚未完成的非守护线程,则 JVM 不会尝试关闭,因此不会调用关闭 Hook 。

如果尝试将进程作为离散应用程序生命周期(而非服务)的一部分而关闭,则关闭代码不应放置在关闭 Hook 内,而应放置在程序设计终止的适当位置。

关于java - 优雅地关闭线程和执行器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3332832/

相关文章:

java - 通过我的 Google 应用引擎应用程序将大型 excel 文件上传到 bigquery

使用 Mock 进行 Java 测试

java - 模拟无法模拟方法调用

java - 跨 JVM 或应用程序实例或 Tomcat 实例的单例

python - 尝试发出整数信号时pyqt属性错误

java - Android:startActivity() 适用于一个 Activity ,但不适用于另一个 Activity

java - 当等待一个线程的 Future 时,线程执行是否会继续

python - 线程只运行一次函数,并且只返回一次值?如何连续返回函数值?

python - 并发.futures 和 Flask-Executor : how to stop all future threads in a thread?

c# - 如何等待来自不同线程的异步 UI 方法?