簡體   English   中英

使用ExecutorService時正確管理內存

[英]Properly managing memory when using ExecutorService

有一個名為“ ConcurrencyUtils”的實用程序類,它在內部使用ExecutorService

private static final ExecutorService executor = Executors.newCachedThreadPool(new CommonPoolThreadFactory());

如您所見,它使用了一個線程池,該池將按需添加線程。 問題是如果該池中至少有一個線程(如果至少使用util一次),則當主方法執行完成時應用程序卻沒有關閉,因為線程仍然存在並且沒有被垃圾回收...

最初我嘗試使用

public static void close(){
    executor.shutdown();
}

並在程序自然停止執行時調用它。 但是不能保證main方法是最后一個要完成的方法,並且在應用程序終止之前可能還有其他應完成的任務,因此我不知道在哪里調用“ close()”來清理util中的線程。 。

我想知道社區是否可以提示我一種更聰明/更清潔的方式來實現這一目標?

ConcurrencyUtil旨在可以在任何地方使用,我無法創建它的實例,我需要它通過靜態而非實例方法提供其接口。


更新

讓我詳細解釋這種情況,ConcurrencyUtil有自己的pool實現,它提供了有用的方法來鏈接多個可運行對象並在paralell中執行它們,或者讓其中一些等待其他對象完成然后執行...這確實很重要是一個實用程序類,這樣,無論何時您想要使用async()或chain(),都不用擔心它是如何工作的。

現在的示例代碼:

public static void main(String[] args) {
    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            System.out.println("hoooooooooooook");
        }
    });


    ConcurrencyUtil.chain()
            .add(()->System.out.println("task 1"))
            .add(()->System.out.println("task 2"))
            .execute()
            .join();

    System.out.println("main finish");
}

執行此操作時,我將得到以下信息:

created new thread with name [common-pool : thread-1]
created new thread with name [common-pool : thread-2]
task 1 
task 2 
main finish

如您所見,線程池創建了兩個線程並執行並發任務,但那些工作線程仍在活動(處於睡眠狀態)等待新任務,這就是為什么在主要執行完成后應用程序仍在運行...並且關閉鈎子也無法正常工作因為(我想)應用程序被認為是活着的...

現在,由於我無法保證main方法是我的退出點(例如,如果我刪除.join(),它可能是完成執行的可運行對象),這就是為什么我無法最終阻止並關閉ConcurrencyUtil的原因...

有什么想法可以正確完成嗎?

應用程序設計的正確方法是引入一個明確的關閉過程,該過程在任何適當的地方都可以調用。 然后,此過程可以在您的執行程序服務上調用shutdown() ,然后調用awaitTermination() 查看ExecutorService的Javadoc中的完整代碼示例。

除了常規關閉協議之外,您還可以提供JVM關閉鈎子,它將再次啟動相同的關閉過程。 您永遠不應依賴該機制,但是在發生不可預測的故障時這是一件好事。

暫無
暫無

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

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