我正在阅读netty源代码,并将其与jdk源代码进行比较。 我发现jdk在ThreadLocal中使用哈希码,当有很多冲突时它很慢。
所以为什么不像netty中的FastThreadLocal一样使用数组,没有任何哈希冲突,然后直接命中。
答案 0 :(得分:2)
基于散列的方法可能“在存在许多冲突时变慢”,但是没有理由过早地假定存在许多冲突。由于“许多哈希冲突”是许多因素的标志,因此您所谈论的是线性索引方法存在更多问题的情况。
对于积极使用FastThreadLocal
的应用程序并创建使用它们的特定FastThreadLocalThread
实例的应用程序,可能会很好。
当 all 线程必须创建足够大的数组以容纳曾经创建的 all ThreadLocal
实例的值时,此方法无法正常工作。或者,更确切地说,通常是一个甚至更大的数组,以避免每次创建ThreadLocal
时都要重新调整所有数组的大小。
您可以通过延迟扩展数组来降低成本,但是当为所有索引小于该值的本地ThreadLocal
#800设置值时,甚至没有不再存在,因为该方案不支持自动清除。
ThreadLocal
实例可以自动收集垃圾,几乎没有影响,这与必须遍历所有线程并重新排列其数组的清理方法不具有可比性。如果那发生了。我在FastThreadLocal
代码中找不到这种清除方法。因此,它似乎只是在增长。对于标准的JRE解决方案,这显然是不可接受的。
答案 1 :(得分:0)
@Holger你是对的。谢谢。
这些天,我阅读了JDK源代码和netty源代码后,我想我明白了为什么jdk使用哈希表,而netty使用公共数组。
JDK使用哈希表,因为当不再使用线程局部变量时,可以释放变量,并且可以调整哈希表的大小以避免内存泄漏。因此,JDK使用WeakReference作为条目来自动释放内存,并使用0x61c88647减少哈希冲突。
但实际上,为了提高搜索效率,它使用通用数组,并且不再自动释放内存。 netty可以手动删除线程的所有线程局部变量,只需使用removeAll()方法即可。