使用ExecutorService时正确管理内存

时间:2014-09-16 12:23:11

标签: java multithreading concurrency garbage-collection

有一个名为“ConcurrencyUtils”的实用程序类,它在内部使用ExecutorService

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

正如您所看到的,它使用了一个线程池,可以根据需要添加线程。问题是如果该池中至少有一个线程(如果util至少使用一次),那么当主方法执行完成应用程序但是没有关闭时,因为线程仍处于活动状态并且没有被垃圾收集... < / p>

最初我尝试过使用

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

并在程序自然停止执行时调用它。但是不能保证main方法是最后一个要完成的,并且可以在应用程序终止之前完成其他任务,因此我不知道在哪里调用“close()”来清除util中的线程。

我想知道社区是否可以暗示我采用更智能/更清洁的方式来实现这一目标?

ConcurrencyUtil可以在任何地方使用,我无法创建它的实例我需要它通过静态非实例方法提供它的接口。


更新

让我详细解释一下这个案例,ConcurrencyUtil有自己的pool实现,它提供了有用的方法来链接几个runnable并在paralell中执行它们或让其中一些等待othero完成然后执行... doesent重要的是它应该是一个实用程序类,以便每当你想要使用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

正如您所看到的,线程池创建了两个线程并执行并发任务,但这些工作线程仍处于活动状态(处于休眠状态),等待新任务,这就是为什么在主执行完成后应用程序仍在运行...而且shutdown hook是(我猜)应用程序被认为是活着的......

现在假设我不能保证main方法是我的退出点(例如,如果我删除.join(),它可能是一个完成执行的runnable)这就是为什么我不能放置finally块并关闭ConcurrencyUtil ...

任何想法如何正确完成?

1 个答案:

答案 0 :(得分:1)

应用程序设计的正确方法是引入一个显式关闭过程,该过程在适当的地方调用。然后,此过程可以在您的执行程序服务上调用shutdown(),然后调用awaitTermination()。查看ExecutorService的Javadoc以获取完整的代码示例。

除了常规关闭协议之外,您还可以提供JVM关闭挂钩,它将再次启动相同的关闭过程。你永远不应该依赖这个机制,但如果出现不可预测的失败,这是件好事。