接着上次手撕面试题ThreadLocal!!!面试官一听,哎呦不错哦!本文将继续上文的话题,来聊聊FastThreadLocal,目前关于FastThreadLocal的很多文章都有点老有点过时了(本文将澄清几个误区),很多文章关于FastThreadLocal介绍的也不全,希望本篇文章可以带你彻底理解FastThreadLocal!!!
FastThreadLocal是Netty提供的,在池化内存分配等都有涉及到!
关于FastThreadLocal,零度准备从这几个方面进行讲解:
FastThreadLocal的使用。
FastThreadLocal并不是什么情况都快,你要用对才会快。
FastThreadLocal利用字节填充来解决伪共享问题。
FastThreadLocal比ThreadLocal快,并不是空间换时间。
FastThreadLocal不在使用ObjectCleaner处理泄漏,必要的时候建议重写onRemoval方法。
FastThreadLocal为什么快?
FastThreadLocal的使用FastThreadLocal用法上兼容ThreadLocal
FastThreadLocal使用示例代码:
public class FastThreadLocalTest { private static FastThreadLocal<Integer> fastThreadLocal = new FastThreadLocal<>(); public static void main(String[] args) { //if (thread instanceof FastThreadLocalThread) 使用FastThreadLocalThread更优,普通线程也可以 new FastThreadLocalThread(() -> { for (int i = 0; i < 100; i++) { fastThreadLocal.set(i); System.out.println(Thread.currentThread().getName() + "====" + fastThreadLocal.get()); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } }, "fastThreadLocal1").start(); new FastThreadLocalThread(() -> { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + "====" + fastThreadLocal.get()); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } }, "fastThreadLocal2").start(); } }代码截图:
代码运行结果:
我们在回顾下之前的ThreadLocal的 最佳实践做法:
try { // 其它业务逻辑 } finally { threadLocal对象.remove(); }备注: 通过上面的例子,我们发现FastThreadLocal和ThreadLocal在用法上面基本差不多,没有什么特别区别,个人认为,这就是FastThreadLocal成功的地方,它就是要让用户用起来和ThreadLocal没啥区别,要兼容!
使用FastThreadLocal居然不用像ThreadLocal那样先try ………………… 之后finally进行threadLocal对象.remove();
由于构造FastThreadLocalThread的时候,通过FastThreadLocalRunnable对Runnable对象进行了包装:
FastThreadLocalRunnable.wrap(target)从而构造了FastThreadLocalRunnable对象。FastThreadLocalRunnable在执行完之后都会调用FastThreadLocal.removeAll();
备注: FastThreadLocal不在使用ObjectCleaner处理泄漏,必要的时候建议重写onRemoval方法。关于这块将在本文后面进行介绍,这样是很多网上资料比较老的原因,这块已经去掉了。
如果是普通线程,还是应该最佳实践:
finally {
fastThreadLocal对象.removeAll();
}
注意: 如果使用FastThreadLocal就不要使用普通线程,而应该构建FastThreadLocalThread,关于为什么这样,关于这块将在本文后面进行介绍:FastThreadLocal并不是什么情况都快,你要用对才会快。
FastThreadLocal并不是什么情况都快,你要用对才会快首先看看netty关于这块的测试用例:
代码路径:https://github.com/netty/netty/blob/4.1/microbench/src/main/java/io/netty/microbench/concurrent/FastThreadLocalFastPathBenchmark.java
备注: 在我本地进行测试,FastThreadLocal的吞吐量是jdkThreadLocal的3倍左右。机器不一样,可能效果也不一样,大家可以自己试试,反正就是快了不少。
关于ThreadLocal,之前的这篇:手撕面试题ThreadLocal!!!已经详细介绍了。
FastThreadLocal并不是什么情况都快,你要用对才会快!!!
注意: 使用FastThreadLocalThread线程才会快,如果是普通线程还更慢!
注意: 使用FastThreadLocalThread线程才会快,如果是普通线程还更慢!
注意: 使用FastThreadLocalThread线程才会快,如果是普通线程还更慢!
netty的测试目录下面有2个类:
FastThreadLocalFastPathBenchmark
FastThreadLocalSlowPathBenchmark
路径:https://github.com/netty/netty/blob/4.1/microbench/src/main/java/io/netty/microbench/concurrent/
FastThreadLocalFastPathBenchmark测试结果: 是ThreadLocal的吞吐量的3倍左右。
FastThreadLocalSlowPathBenchmark测试结果: 比ThreadLocal的吞吐量还低。
测试结论: 使用FastThreadLocalThread线程操作FastThreadLocal才会快,如果是普通线程还更慢!
注释里面给出了三点: