java - ExecutorService 是否在超出范围时收集垃圾?

标签 java multithreading garbage-collection java-8 executorservice

我问这个问题是因为我正在创建很多执行程序服务,虽然我可能已经在某个地方有内存泄漏需要调查,但我认为最近对以下代码的更改实际上使它变得更糟,因此我是试图确认发生了什么:

@FunctionalInterface
public 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完成了吗?

最佳答案

Does the ExecutorService service go out of scope and get garbage collected once BaseConsumer.accept() has finished?

是的。

的确,关联的线程池也应该被垃圾回收……最终。

Executors.newSingleThreadExecutor() 创建的 ExecutorServiceFinalizableDelegatedExecutorService 的一个实例。该类具有 finalize() 方法,该方法在包装的 ExecutorService 对象上调用 shutdown()。如果所有未完成的任务实际终止,服务对象将关闭其线程池。

(据我所知,这不是指定的。但它是根据源代码实现的,在 Java 6 之后。)


Does adding a finally { service.shutdown(); } in the try-catch around future.get() help in retrieving resources quicker? (not necessarily garbage collecting the service object).

是的。调用 shutdown() 会导致线程在未完成的任务完成后立即释放。该过程会立即开始,而如果您只是将其留给垃圾收集器处理,则在调用终结器之前它不会开始。

现在,如果资源只是“普通”Java 对象,这就没有关系了。但在这种情况下,您要回收的资源是一个 Java 线程,它具有关联的操作系统资源(例如 native 线程)和一个重要的堆外内存块。所以这样做可能是值得的。

但如果您希望对此进行优化,也许您应该创建一个长期存在的 ExecutorService 对象,并在多个“消费者”实例之间共享它。

关于java - ExecutorService 是否在超出范围时收集垃圾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24953978/

相关文章:

multithreading - 我可以获得持有 CriticalSection 的线程的 id 吗?

java - 多态继承

java - JPA EntityManager 不一致地将对象添加到数据库

python - 跨线程共享 Django 事务

java - 如果不中断,Future.cancel() 会做什么?

c# - 我如何明确清除字节 []

java - 无法将 List<Object[]> 值分配给特定类型的 ArrayList

java - 用于返回用户输入字符串中的元音的 Junit 测试?

javascript - 是否收集了 WebGLTextures 垃圾?

java - Java 中的清除 protected 双向链表