簡體   English   中英

如何在不丟失任務的情況下關閉和重新實例化 Executor Service

[英]How to shutdown and reinstantiate an Executor Service without loosing tasks

我不完全理解,我應該如何在應用程序中實現一個 ExecutorService ,偶爾會有即將到來的任務。 每個任務運行大約 15 分鍾(更長的時間)。 有時一天有 10 個任務,有時一整周都沒有。

因此,如果隊列中沒有剩余任務,則在執行某些任務后,我想關閉執行程序,因為它不再需要,以便垃圾收集器可以完成其工作。 調用關閉后,沒有新任務排隊到執行程序。

現在,我的問題是我必須確保所有任務都已完成。 這意味着,在調用shutdown 之后,我必須確保在提交新任務之前實例化了一個新的Executor Service。 我必須等到舊的 Executor Service 關閉(或終止?)並啟動一個新的。 我應該如何實現這個?

這是我的方法:

// sync block to check for each task if a new Executor Service has to be created before submitting the task
synchronized (this) {
    // do I have to check both isSutdown and isTerminated?
    if (null == businessTaskExecutor || businessTaskExecutor.isShutdown() || businessTaskExecutor.isTerminated()) {
        // simply init a new one
        businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
    } else if (businessTaskExecutor.isTerminating()) {
        // the termination process has started and is not done.
        // Do I have to wait for the old executor or can I simply init a new one without waiting?
        while (!businessTaskExecutor.isTerminated()) { }
        businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
    }
}
Future<?> future = businessTaskExecutor.submit(() -> new BusinessTaskRunnable(businessTask));
if (future.isDone() && businessTaskExecutor.getQueue().isEmpty()) {
    businessTaskExecutor.shutdown();
    try {
        if (!businessTaskExecutor.awaitTermination(1, TimeUnit.HOURS)) {
            businessTaskExecutor.shutdownNow();
        }
    } catch (InterruptedException ex) {
        businessTaskExecutor.shutdownNow();
        Thread.currentThread().interrupt();
    }
}

解釋:

如果執行者為空/關閉/終止,我會啟動一個新的,到目前為止一切都很好。 否則,如果執行程序當前正在終止(因為調用了 shutdown),執行程序將不會接受進一步的任務。 所以我等到它被終止,然后再啟動一個新的。 之后我提交我的任務......如果隊列中沒有其他任務,我只會關閉執行程序。 盡管我等了一個小時,因為仍然可能有一個正在運行的任務。

我希望的行為有更好的實現嗎?

附加信息:我使用 ThreadPoolExecutor 因為我需要 getQueue() 來檢查它是否為空。 我還可以在不同的實現中使用任何其他類型的 Executor Service。

提前致謝。

我想關閉執行程序,因為它不再需要,以便垃圾收集器可以完成它的工作。

但它必需的,這就是你要重新創建它的原因。 無論執行器是否關閉,GC 都可以完成它的工作(除非您設法創建了一些非常特別的東西,例如ThreadLocal會以某種方式將對象綁定到執行器)。

我讀到只有當我關閉執行程序時才會調用垃圾收集器。

您要么記錯了,要么正在閱讀錯誤的信息。

由於您使用單線程運行,因此您甚至不需要擔心池配置。 一個長壽的Executors.newFixedThreadPool(1); 是你所需要的全部。

如果您確實需要釋放資源,您可以使用new ThreadPoolExecutor(0, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<BusinessTaskRunnable>());之類的配置核心池大小 . 但那是無關緊要的微優化,一個線程不應該有所作為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM