作为一个程序猿,都应该知道单例模式,实现方式有很多种,懒汉式,线程不安全;懒汉式,线程安全;恶汉式;恶汉式,变种;静态内部类;双重检验锁;登记式。这些方式各有各的好处,这些在网上都可以搜索到很多,以上这些都是进程级别的单例模式。
今天在研究dubbo源码时,无意中发现一种实现线程级的单例模式,借助于ThreadLocal,详情用代码说话:
public class RpcContext {
private static final ThreadLocal<RpcContext> LOCAL =
new ThreadLocal<RpcContext>() {
@Override
protected RpcContext initialValue() {
return new RpcContext();
}
};
public static RpcContext getContext() {
return LOCAL.get();
}
}
以上代码可以看出,每个线程获取的都是不同的RpcContext实例,而相同线程都是获取的同一个实例
测试代码如下:
public static void main(String[] args) {
for (int i = 0; i < 10 ; i++) {
new Thread() {
@Override
public void run() {
LocalInteger local = LocalInteger.get();
System.out.println(local);
}
}.start();
}
}
输出结果为:
com.alibaba.LocalInteger@104369f7
com.alibaba.LocalInteger@739e558c
com.alibaba.LocalInteger@7b267845
com.alibaba.LocalInteger@359d9ad4
com.alibaba.LocalInteger@1ce3f103
com.alibaba.LocalInteger@79899753
com.alibaba.LocalInteger@68a20a11
com.alibaba.LocalInteger@2e2f95db
com.alibaba.LocalInteger@3837011a
com.alibaba.LocalInteger@6c6e100b
以上输出的实例hash值都不同。
⚠️注意:请看以下代码:
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10 ; i++) {
executorService.execute(new Thread() {
public void run() {
LocalInteger localInteger = LocalInteger.get();
System.out.println(localInteger);
}
});
}
executorService.shutdown();
}
这时输出的结果是:
com.alibaba.LocalInteger@580b8a57
com.alibaba.LocalInteger@2385d296
com.alibaba.LocalInteger@2385d296
com.alibaba.LocalInteger@580b8a57
com.alibaba.LocalInteger@2385d296
com.alibaba.LocalInteger@580b8a57
com.alibaba.LocalInteger@2385d296
com.alibaba.LocalInteger@580b8a57
com.alibaba.LocalInteger@2385d296
com.alibaba.LocalInteger@580b8a57
请自行思考,为什么每次都是new Thread,但是却只是得到了两个实例?
关注爱上编程的小白