当前位置: 首页 > 面试题库 >

超出范围时,ExecutorService是否会收集垃圾?

卫增
2023-03-14
问题内容

我问这个问题是因为我正在创建很多执行程序服务,尽管我可能已经在某个地方进行内存泄漏了,需要进行调查,但是我认为对以下代码的最近更改实际上使它更糟,因此,我尝试确认到底是怎么回事:

@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


问题答案:

ExecutorService服务是否超出范围并BaseConsumer.accept()在完成后获得垃圾回收?

是。

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

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

(AFAIK,未指定。但这是根据源代码实现的,从Java 6开始。)

是否添加最后一个{service.shutdown(); }在future.get()的try-
catch中有助于更快地检索资源?(不一定是垃圾收集服务对象)。

是的,它确实。调用shutdown()导致线程在未完成的任务完成后立即释放。该过程将立即开始,而如果您将其留给垃圾收集器,则直到调用终结器才开始。

现在,如果资源只是“普通”
Java对象,那就没关系了。但是在这种情况下,您要回收的资源是Java线程,并且具有关联的操作系统资源(例如本机线程)和非平常的堆外内存块。因此,这样做可能值得。

但是,如果您要优化它,也许您应该创建一个寿命很长的ExecutorService对象,并在多个“消费者”实例之间共享它。



 类似资料:
  • 问题内容: 该问题已发布在某个网站上。我在这里找不到正确的答案,因此我将其再次发布在这里。 我的查询与停止线程无关。让我改一下我的问题。A行(请参见上面的代码)启动一个新线程;和B行使线程引用为空。因此,JVM现在具有一个线程对象(处于运行状态),该对象不存在引用(如B行中的t = null)。所以我的问题是,为什么这个线程(在主线程中不再有引用)一直保持运行状态,直到主线程运行。根据我的理解,线

  • 问题内容: 如果执行以下操作,文件句柄会在Python范围之外时自动关闭吗: 如果没有,如何编写此函数以自动关闭范围? 问题答案: 它应该关闭文件语句中的文件句柄,但是更好的方法是使用块: 有关更多信息,请参见http://docs.python.org/library/stdtypes.html#file.close。

  • 问题内容: 我遇到这样的情况,我的Android应用程序无法及时执行软实时任务,因为调用了Garbage Collector需要花费几毫秒的时间。分配给GC的时间只有几毫秒,不足以错过一些重要的期限,这些期限是从IO设备读取数据的小任务。 我当时正在考虑引入另一个线程,并赋予它轮询重要数据的任务。但是我不确定GC是否挂起所有线程还是仅挂起内存占用线程? 问题答案: 在Patrick Dubroy撰

  • 问题内容: 我有一段代码可以在内存中加载很大的图像。所以打电话似乎是合理的事情 在加载图像之前。据我所知,它毫无问题。 昨天,我决定使用一个名为FindBugs的非常有用的软件来扫描您的代码并报告可能导致错误或通常不建议使用的策略的问题。问题是我提到的这段代码得到了报告。描述是这样的: …强迫垃圾收集;除了基准测试代码外,都非常可疑 并继续阐述: 代码显式调用垃圾回收。除了基准测试中的特定用途外,

  • 问题内容: 为什么使用lambda函数来获取值列表i = 4。在调用lambda期间,不存在封闭范围。函数f已经完成工作并返回了控制(变量i不存在)。 问题答案: Python使用闭包捕获对原始变量的引用。这些对象保留对名称的引用,可以通过该引用访问值。这意味着变量在完成后将继续存在。 您可以在lambda对象的元组中内省此闭包;函数具有相同的属性: 这也是列表中 所有 lambda 都引用val

  • 问题内容: 我知道当分配DirectbyteBuffer时,它不受垃圾回收的限制,但是我想知道的是 包装 对象是否被垃圾回收了。 例如,如果我分配了一个新的DirectByteBuffer dbb,然后使用dbb.duplicate()将其复制(浅复制),则我将在同一块内存中使用两个包装器。 这些包装器是否要进行垃圾收集?如果我做了 我最终会自己OOM吗? 问题答案: 在Sun JDK中,由创建的