有一个名为“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 ...
任何想法如何正确完成?
答案 0 :(得分:1)
应用程序设计的正确方法是引入一个显式关闭过程,该过程在适当的地方调用。然后,此过程可以在您的执行程序服务上调用shutdown()
,然后调用awaitTermination()
。查看ExecutorService
的Javadoc以获取完整的代码示例。
除了常规关闭协议之外,您还可以提供JVM关闭挂钩,它将再次启动相同的关闭过程。你永远不应该依赖这个机制,但如果出现不可预测的失败,这是件好事。