java线程池threadlocal_java – 这是真的我的工作,以清理ThreadLocal资源,当类暴露在线程池?...

叹息,这是老消息

嗯,这个晚会晚了一点。 2007年10月,Josh Bloch(java.lang.ThreadLocal的合着者以及Doug Lea)wrote:

“The use of thread pools demands extreme care. Sloppy use of thread

pools in combination with sloppy use of thread locals can cause

unintended object retention, as has been noted in many places.”

人们都抱怨ThreadLocal与线程池的不良交互,即使那样。但乔施行了制裁:

“针对性能的每线程实例。Aaron的SimpleDateFormat示例(上面)是此模式的一个示例。

一些教训

>如果将任何类型的对象放入任何对象池中,您必须提供一种方法来删除它们“以后”。

>如果你’pool’使用ThreadLocal,你有有限的选择这样做。或者:

a)你知道你放置值的线程将在你的应用程序完成时终止;要么

b)你可以稍后安排相同的线程调用ThreadLocal#set()来调用ThreadLocal#remove(),当你的应用程序终止

>因此,使用ThreadLocal作为对象池将对您的应用程序和您的类的设计造成沉重的代价。福利不是免费的。

>因此,使用ThreadLocal可能是一个过早的优化,即使Joshua Bloch敦促你考虑它在“有效的Java”。

简而言之,决定使用ThreadLocal作为一种快速,无保留地访问“每个线程实例池”的形式不是一个轻率的决定。

注意:除了“对象池”,还有ThreadLocal的其他用途,这些课程不适用于那些只想临时设置ThreadLocal的情况,或者有真正的每线程状态要保留踪迹。

库实现者的后果

Threre对库实现者有一些影响(即使这样的库在您的项目中是简单的实用程序类)。

或者:

>你使用ThreadLocal,完全意识到你可能“污染”长时间运行的线程与额外的行李。如果你正在实现java.util.concurrent.ThreadLocalRandom,它可能是合适的。 (Tomcat可能仍然对你的库的用户,如果你没有实现在Java。*)。有趣的是,注意到java。*使得使用ThreadLocal技术的学科。

要么

>你使用ThreadLocal,并给你的类/包的客户端:

a)有机会选择放弃优化(“不使用ThreadLocal …我不能安排清理”);和

b)一种清理ThreadLocal资源的方法(“使用ThreadLocal …我可以安排所有线程,使用你调用LibClass.releaseThreadLocalsForThread()当我完成他们。

使你的库难以正常使用,虽然。

要么

>你给你的客户机提供他们自己的对象池impelementation(这可能使用ThreadLocal,或某种同步)。 (“OK,我可以给你一个新的ExpensiveObjectFactory< T>(){public T get(){…}}如果你认为它是真正neccesasry”。

不是那么坏。如果对象真的那么重要,创建昂贵,显式池可能是值得的。

要么

>你决定它对你的应用程序不值得多,找到一个不同的方法来解决问题。那些昂贵的创建,可变,非线程安全的对象正在导致你痛苦…正在使用他们真的最好的选择吗?

备择方案

>正则对象池,与其所有竞争同步。

>不集合对象 – 只是在本地范围内实例化它们,并稍后丢弃。

>不汇集线程(除非你可以安排清理代码,当你喜欢) – 不要使用你的东西在JaveEE容器

>线程池,它足够聪明,可以清理ThreadLocals,而不会在你身上。

>线程池,在每个应用程序的基础上分配线程,然后让它们在应用程序停止时死亡。

>线程池容器和应用程序之间的协议,允许注册“应用程序关闭处理程序”,容器可以安排在已用于服务应用程序的线程上运行…在将来的某个时间,当该线程是下一个可用。例如。 servletContext.addThreadCleanupHandler(new Handler(){@Override cleanup(){…}})

在未来的JavaEE规范中,看到最后3个项目的一些标准化是很好的。

Bootnote

实际上,GregorianCalendar的实例化相当轻量级。这是不可避免的调用setTime(),它引发大部分的工作。它也不保持线程的运行的不同点之间的任何显着状态。将日历放到ThreadLocal中不太可能给你带来更多的代价,除非分析显然在新的GregorianCalendar()中显示了热点。

新的SimpleDateFormat(String)比较昂贵,因为它必须解析格式字符串。一旦被解析,对象的“状态”对于以后由相同线程使用是重要的。这是一个更好的适合。但是,它可能仍然是“更便宜”实例化一个新的,比给你的类额外的责任。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值