gpt4 book ai didi

java - 为什么 Java ThreadPoolExecutor 会覆盖 finalize()

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:48:47 25 4
gpt4 key购买 nike

我想知道为什么 ThreadPoolExecutor finalize() 方法调用它的 shutdown() 方法,而已知 finalize 方法只被 GC AFTER 它的所有线程都已停止。那么,为什么 ThreadPoolExecutor 会完全覆盖 finalize()

ThreadPoolExecutor.finalize() 调用 shutdown() 似乎误导了我(以及我的项目线程泄漏的来源),因为这给人一种强烈的(但错误的)印象- ThreadPoolExecutor 管理其线程的生命周期,并在 GC 收集 ThreadPoolExecutor 对象时停止线程- 只需要调用 shutdown() 或 shutdownNow() 如果你想要确定的结果而不是依赖 GC 来清理(显然,这样做是不好的做法!)

注意事项在这个线程中,why-doesnt-this-thread-pool-get-garbage-collected Affe 解释了为什么客户端仍然需要调用 shutdown()

在此线程中,why-threadpoolexecutor-finalize-invokes-shutdown-and-not-shutdownnow发起人对此主题感到困惑,但答案并不像1 中的那样全面

JavaDocs对于 ThreadPoolEecutor.finalize() 确实包含“并且它没有线程”这句话,但这很容易被忽略。

最佳答案

首先,如果您认为这是一个错误,请将其报告给 Oracle。

其次,我们无法肯定地回答您的问题,因为您实质上是在问“他们为什么要这样设计”……而当他们做出决定时我们不在场。

但我怀疑原因是当前的选择被认为是两害相权取其轻:

  • 一方面,如果您的线程池可能仅仅因为它不再被直接引用而被关闭,那么正在执行实际工作的线程可能会过早终止。

  • 另一方面,正如您所观察到的,如果线程池在变得更长时间可直接访问时不会自动关闭,则可能是内存泄漏。

鉴于显然有避免存储泄漏的方法,我认为第二种选择(即当前行为)是弊端中的较小者。

无论如何,有明确的证据表明设计者考虑到了这种行为;即来自 ThreadPoolExecutor javadoc 的引用:

Finalization

A pool that is no longer referenced in a program AND has no remaining threads will be shutdown automatically. If you would like to ensure that unreferenced pools are reclaimed even if users forget to call shutdown(), then you must arrange that unused threads eventually die, by setting appropriate keep-alive times, using a lower bound of zero core threads and/or setting allowCoreThreadTimeOut(boolean).

(以及那种回答的@fge 的评论。当不活动的工作线程被配置为超时时会发生这种情况。)

我也认为还有一个基于实现的原因。看一下代码 here .

线程池中的每个线程都有一个Runnable的引用,它实际上是内部类ThreadPoolExecutor.Worker的一个实例。这意味着存在从( Activity 的,尽管可能是空闲的)ThreadThreadPoolExecutor.Worker 对象,以及从该对象到封闭的 的强引用路径ThreadPoolExecutor 实例。由于 Activity 线程始终可访问,因此 ThreadPoolExecutor 实例将保持可访问状态,直到其所有线程实际终止为止。

现在我/我们无法告诉您哪个先出现,行为还是 javadoc 规范。请参阅我上面的“其次...”点...

但是,就像我上面所说的(“首先...”),如果您认为这是一个错误,请将其报告给 Oracle。如果您认为 javadoc 具有误导性,情况也是如此……尽管鉴于我引用的 Material ,我认为您的论点很薄弱。


至于如果 shutdown() 在这种情况下什么都不做,为什么他们重​​载 finalize() 来调用 shutdown():

  • 它可能在早期版本中做了一些重要的事情,并且

  • shutdown() 方法以调用 Hook 方法结束,该 Hook 方法显然在子类中被覆盖以执行一些重要的事情......根据评论。

关于java - 为什么 Java ThreadPoolExecutor 会覆盖 finalize(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22558304/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com