ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

为什么Java ThreadPoolExecutor覆盖finalize()

2019-11-22 00:01:21  阅读:342  来源: 互联网

标签:threadpoolexecutor multithreading java garbage-collection


我想知道为什么在终止所有线程之后,仅当GC调用finalize方法时,ThreadPoolExecutor finalize()方法才会调用其shutdown()方法的原因.那么,为什么ThreadPoolExecutor会完全覆盖finalize()?

ThreadPoolExecutor.finalize()调用shutdown()对我(以及我的项目的线程泄漏源)似乎具有误导性,因为这给人以强烈(但错误的)印象,即
-ThreadPoolExecutor管理其线程的生命周期,并在GC收集ThreadPoolExecutor对象时停止线程
-仅在需要确定性结果而不是依靠GC进行整理的情况下才需要调用shutdown()或shutdownNow()(显然,这样做的错误做法!)

笔记
在该线程中,why-doesnt-this-thread-pool-get-garbage-collected Affe解释了为什么客户端仍然需要调用shutdown()

在这个主题中,始发者why-threadpoolexecutor-finalize-invokes-shutdown-and-not-shutdownnow对此主题感到困惑,但答案却不如1中的全面.

ThreadPoolEecutor.finalize()的JavaDocs确实包含单词“并且它没有线程”,但这很容易被忽略.

解决方法:

首先,如果您认为这是一个错误,则将其报告给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的实例.这意味着从(活动的,虽然可能是空闲的)线程到ThreadPoolExecutor.Worker对象,再从该对象到封闭的ThreadPoolExecutor实例,都有一个强大的引用路径.并且由于活动线程始终是可访问的,因此ThreadPoolExecutor实例在所有线程真正终止之前仍可访问.

现在,我/我们无法告诉您行为或javadoc规范是第一个出现的.参见上方的“第二…”点…

但是,就像我上面说的(“首先…”)一样,如果您认为这是一个错误,请向Oracle报告.如果您认为javadoc具有误导性,也是如此……尽管我认为您的论点在我引用的材料中仍然很弱.

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

>在较早的版本中,它可能做了重要的事情,并且
> shutdown()方法以调用挂钩方法结束,该挂钩方法显然在子类中被重写以执行重要的工作……根据注释.

标签:threadpoolexecutor,multithreading,java,garbage-collection
来源: https://codeday.me/bug/20191121/2055797.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有