超出范围时,ExecutorService是否会收集垃圾?
我问这个问题是因为我正在创建很多执行程序服务,尽管我可能已经在某个地方进行内存泄漏了,需要进行调查,但是我认为对以下代码的最近更改实际上使它更糟,因此,我尝试确认到底是怎么回事:
@FunctionalInterfacepublic interface BaseConsumer extends Consumer<Path> {
@Override
default void accept(final Path path) {
String name = path.getFileName().toString();
ExecutorService service = Executors.newSingleThreadExecutor(runnable -> {
Thread thread = new Thread(runnable, "documentId=" + name);
thread.setDaemon(true);
return thread;
});
Future<?> future = service.submit(() -> {
baseAccept(path);
return null;
});
try {
future.get();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
throw new RuntimeException(ex);
}
}
void baseAccept(final Path path) throws Exception;
}
然后,这Consumer<Path>
会在(通常)N = 2个线程的另一个线程池上被调用,我不确定这是否相关。
问题是:一旦完成,是否ExecutorService service
超出范围 并 获取垃圾BaseConsumer#accept
?
回答:
ExecutorService服务是否超出范围并
BaseConsumer.accept()
在完成后获得垃圾回收?
是。
确实,关联的线程池也应该最终被垃圾回收。
该ExecutorService
由创建Executors.newSingleThreadExecutor()
的实例FinalizableDelegatedExecutorService
。该类具有finalize()
调用shutdown()
包装ExecutorService
对象的方法。如果所有未完成的任务实际上终止,则服务对象将关闭其线程池。
(AFAIK,未指定。但这是根据源代码实现的,从Java 6开始。)
是否添加最后一个{service.shutdown(); }在future.get()的try-
catch中有助于更快地检索资源?(不一定是垃圾收集服务对象)。
是的,它确实。调用shutdown()
导致线程在未完成的任务完成后立即释放。该过程将立即开始,而如果您将其留给垃圾收集器,则直到调用终结器才开始。
现在,如果资源只是“普通”
Java对象,那就没关系了。但是在这种情况下,您要回收的资源是Java线程,并且具有关联的操作系统资源(例如本机线程)和非平常的堆外内存块。因此,这样做可能值得。
但是,如果您要优化它,也许您应该创建一个寿命很长的ExecutorService
对象,并在多个“消费者”实例之间共享它。
以上是 超出范围时,ExecutorService是否会收集垃圾? 的全部内容, 来源链接: utcz.com/qa/397475.html