【发布时间】:2014-09-16 12:23:11
【问题描述】:
有一个名为“ConcurrencyUtils”的实用程序类在内部使用 ExecutorService
private static final ExecutorService executor = Executors.newCachedThreadPool(new CommonPoolThreadFactory());
如您所见,它使用了一个线程池,可以按需添加线程。问题是,如果该池中至少有一个线程(如果至少使用了一次 util),那么当主方法执行完成应用程序但没有关闭时,因为线程仍然存在并且没有被垃圾收集......
最初我尝试过使用
public static void close(){
executor.shutdown();
}
并在程序自然停止执行时调用它。但是不能保证 main 方法是最后一个要完成的方法,并且在应用程序终止之前可能还有其他任务应该完成,因此我不知道在哪里调用“close()”来清除 util.. .
我想知道社区是否可以提示我一种更智能/更清洁的实现方式?
ConcurrencyUtil 旨在可在任何地方使用,我无法创建它的实例,我需要它通过静态而非实例方法提供其接口。
更新
让我详细解释一下这个案例,ConcurrencyUtil 有它自己的 pool 实现,它提供了有用的方法来链接多个 runnables 并并行执行它们,或者让它们中的一些等待其他完成然后执行......确实不管它应该是一个实用程序类,这样当你想要使用 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() )这就是为什么我不能放置 finally 块并关闭 ConcurrencyUtil...
任何想法如何正确完成?
【问题讨论】:
-
关闭钩子只能用作破解代码的变通方法。正确设计的应用程序具有正确设计的关闭程序。
-
我不知道那门课。它是否有一个构造函数可以让你传入你自己的 ExecutorService?任何使用 ExecutorService 的库都应该为客户端提供一种方法。 (并不是说他们都做过,但如果他们都做过,世界会变得更美好。)
-
@Vach 如果您的任务需要执行任何关键清理,那么使用守护线程是危险的。这些线程将在关闭时突然被杀死。正确的设计要求可中断线程。
-
我总是有一个地方可以打电话给
shutdown()。当然,ThreadPool确实定义了一个终结器方法,它调用shutdown()。
标签: java multithreading concurrency garbage-collection