从ThreadLocal
变量读取比从常规字段读取慢多少?
更具体地说,创建简单对象比访问ThreadLocal
变量快还是慢?
我假设它足够快,所以拥有ThreadLocal<MessageDigest>
实例比每次创建MessageDigest
实例要快得多。但例如,这是否也适用于byte10或byte1000?
编辑:问题是在调用ThreadLocal
的get时到底发生了什么?如果这只是一个字段,就像其他任何字段一样,那么答案应该是“它总是最快的”,对吧?
发布于 2009-03-04 11:56:55
运行未发布的基准测试,在我的机器上,ThreadLocal.get
每次迭代大约需要35个周期。不是很多。在Sun的实现中,Thread
中的自定义线性探测散列映射将ThreadLocal
映射到值。因为它只被单个线程访问,所以它可以非常快。
小对象的分配需要类似的周期数,尽管由于缓存耗尽,在紧凑的循环中可能会得到一些较低的数字。
MessageDigest
的建设可能会相对昂贵。它有相当多的状态,并通过Provider
的SPI机制进行构造。例如,您可以通过克隆或提供Provider
来进行优化。
仅仅因为在ThreadLocal
中缓存可能比在create中缓存更快,并不一定意味着系统性能会提高。你会有额外的与GC相关的开销,这会减慢一切。
除非您的应用程序大量使用MessageDigest
,否则您可能需要考虑使用传统的线程安全缓存。
发布于 2009-03-04 11:36:20
在2009年,一些JVM在Thread.currentThread()
对象中使用非同步HashMap
实现了ThreadLocal
。这使得它非常快(当然,不像使用常规字段访问那样快),并确保在Thread
终止时ThreadLocal
对象得到清理。在2016年更新这个答案,看起来大多数(所有?)较新的JVM使用带线性探测的ThreadLocalMap
。我不确定这些实现的性能--但我不能想象它会比早期的实现更糟糕。
当然,现在new Object()
的速度也非常快,垃圾收集器也非常擅长回收生命周期较短的对象。
除非您确定对象创建的开销很大,或者您需要逐个线程地保存某些状态,否则您最好选择更简单的在需要时分配解决方案,并且只在分析器告诉您需要时才切换到ThreadLocal
实现。
发布于 2009-03-04 10:14:48
在优化之前,@Pete是正确的测试。
如果与实际使用相比,构建MessageDigest有任何严重的开销,我会感到非常惊讶。
错过使用ThreadLocal可能是泄漏和悬空引用的来源,这些都没有明确的生命周期,通常我不会使用ThreadLocal,除非我对何时删除特定资源有一个非常明确的计划。
https://stackoverflow.com/questions/609826
复制相似问题