超出范围时,ExecutorService是否会收集垃圾?
我问这个问题是因为我正在创建大量的执行程序服务,虽然我可能已经在需要调查的地方发生内存泄漏,但我认为最近对以下代码的更改实际上使其恶化,因此我试图确认到底是怎么回事:
@FunctionalInterface public interface BaseConsumer extends Consumer { @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; }
然后在另一个具有(通常)N = 2个线程的线程池上调用此Consumer
,我不确定这是否相关。
问题是:一旦BaseConsumer#accept
完成, ExecutorService service
是否超出范围并收集垃圾?
一旦
BaseConsumer.accept()
完成,ExecutorService服务是否超出范围并收集垃圾?
是。
实际上,关联的线程池也应该被垃圾收集……最终。
ExecutorService
由Executors.newSingleThreadExecutor()
创建的Executors.newSingleThreadExecutor()
实例。 该类具有finalize()
方法,该方法在包装的ExecutorService
对象上调用shutdown()
。 如果所有未完成的任务实际终止,则服务对象将关闭其线程池。
(AFAIK,这没有指定。但它是根据源代码实现的,在Java 6以后。)
是否添加了finally {service.shutdown(); 在future.get()中的try-catch帮助更快地检索资源? (不一定是垃圾收集服务对象)。
是的,它确实。 调用shutdown()
会在未完成的任务完成后立即释放线程。 该过程立即开始,而如果你把它留给垃圾收集器,它将不会启动,直到调用终结器。
现在,如果资源只是“普通”Java对象,那么这无关紧要。 但在这种情况下,您要回收的资源是Java线程,并且具有关联的操作系统资源(例如本机线程)和非平凡的堆外存储器块。 所以这样做可能是值得的。
但是如果你想要优化它,也许你应该创建一个长期存在的ExecutorService
对象,并在多个“消费者”实例之间共享它。
我想让执行发生在命名线程上,它与更容易记录有关。 在任何一种情况下,此代码都应该有效。
你可以更简单/更快地完成这项工作
Thread t = Thread.currentThread(); String name = t.getName(); try { t.setName("My new thread name for this task"); // do task } finally { t.setName(name); }
这样,您可以使用命名线程而无需创建新线程。
- 如何使用invokeAll()让所有线程池完成他们的任务?
- 如何在FutureTask中捕获exception
- 在ExecutorService中hibernate一个线程(Java / Clojure)
- 如何在使用具有线程超时function的ExecutorService时提高性能?
- ExecutorService,如何知道所有线程何时完成而不阻塞主线程?
- 是否使用invokeAll或submit – java Executor服务
- 在ExecutorService上安排的守护程序线程; 解释为什么这是不好的forms
- Control ExecutorService每秒最多执行N个任务
- 完成所有ExecutorService任务后,程序不会立即终止