容器单例模式

之前学习Structs2,Spring框架时,经常会听到单例,多例。虽然这与单例模式不太一样,但是都很类似。在程序运行的时候,就加载所有的实例,然后用的时候直接取出

看下面代码:

/**
* @program: designModel
* @description: 容器单例模式
* @author: YuKai Fan
* @create: 2018-12-11 14:59
**/
public class ContaineSingleton {
private ContaineSingleton() {}
private static Map<String, Object> singletonMap = new HashMap<String, Object>(); public static void putInstance(String key, Object instance) {
if (StringUtils.isNotBlank(key) && instance != null) {
if (!singletonMap.containsKey(key)) {
singletonMap.put(key, instance);
}
}
} public static Object getInstance(String key) {
return singletonMap.get(key);
}
}

但是,这种方式在不考虑序列化与反射的情况下,依旧是不安全的。因为在多线程的环境下,还是会产生不同的实例,这需要结合场景来使用。

如果使用hashTable来保证线程安全的话,效率会很低,频繁去取实例都回家加同步锁。如果使用ConcurrentHashMap,由于被static修饰,相当于直接操作了 map,在这种场景下,也不是绝对的线程安全。

ThreadLocal环境下的"单例模式"

这种带引号的单例模式,并不是真正的单例模式。因为并不能保证整个应用只产生一个实例,只会保证整个应用线程唯一

/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-12-11 15:17
**/
public class ThreadLocalInstance {
private static final ThreadLocal<ThreadLocalInstance> threadLocalInstance = new ThreadLocal<ThreadLocalInstance>(){
@Override
protected ThreadLocalInstance initialValue() {
return new ThreadLocalInstance();
}
};
private ThreadLocalInstance() {} public static ThreadLocalInstance getInstance() {
return threadLocalInstance.get();
} }
/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-12-04 14:11
**/
public class T implements Runnable {
public void run() { ThreadLocalInstance instance = ThreadLocalInstance.getInstance();
System.out.println(Thread.currentThread().getName() + "" + instance); }
}
/**
* @program: designModel
* @description:
* @author: YuKai Fan
* @create: 2018-12-04 14:07
**/
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// LazySingleton lazySingleton = LazySingleton.getInstance();
Thread t1 = new Thread(new T());
Thread t2 = new Thread(new T());
t1.start();
t2.start();
System.out.println("测试");
}
}

输出结果:

产生的是不同的实例,但是ThreadLocal回味每个线程提供独立的变量副本,将每个线程的实例隔离。保证在多线程的情况下,会保证每个线程只能产生一个实例

单例模式源码分析

单例模式在jdk下的应用:

java.lang.Runtime下的getRuntime()方法,属于饿汉式

AWT下的Desktop类中的getDesktop()——容器单例的影子

Spring中的单例与之前介绍的单例不一样,

spring中的单例是在bean作用域中的一个,这个作用域在每个应用程序上下文中仅创建一个我们设置单例属性的这个实例;与之前介绍的单例模式最大的区别在于Spring讲实例的数量限制在每个应用程序的上下文,而之前的单例模式中的实例,是将数量限制在给定的类加载器管理的整个空间里。所以Spring容器中,即使设置属性为单例,都可以拿出来这个对象。

在AbstractFactoryBean中的getObject()方法,可以看到单例模式的影子。

MyBatis中的单例模式:

ErrorContext类,保证每个线程的各自数据,使用的就是单例模式,也就是ThreadLocal的单例模式。

最新文章

  1. OpenStack调研:OpenStack是什么、版本演变、组件关系(Havana)、同类产品及个人感想
  2. 查看python api
  3. Yii2框架RESTful API教程(一) - 快速入门
  4. 筛选DataTable数据的方法
  5. 深度神经网络如何看待你,论自拍What a Deep Neural Network thinks about your #selfie
  6. bzoj 3732 Network(最短路+倍增 | LCT)
  7. 制作font-icon有感
  8. js 异步流程控制之 avQ(avril.queue)
  9. MFC 操作控件数据
  10. arm+linux 裸机环境搭建之安装工具篇(eclipse)
  11. linux远程登录ssh免密码
  12. RADIUS and IPv6[frc-3162译文]
  13. 关于*.ashx 处理程序调试时 未能创建类型 错误
  14. JAVA核心技术I---JAVA基础知识(常量设计和常量池)
  15. JAVA 重写equals和重写hashCode
  16. 什么是pytorch(2Autograd:自动求导)(翻译)
  17. pycharm如何全局进行查找一个关键词
  18. 51NOD 1046 A^B Mod C
  19. 【转】SQL FOR XML简介及用法
  20. Spring+Mybatis整合时 Failed to read candidate component class,Caused by:IllegalArgumentException

热门文章

  1. Tomcat&amp;Servlet
  2. thinkphp5使用uploadify
  3. tp5分页注意,分页生成的ul class是pagination,有些模板可能将pagination定义为display:none
  4. thinkphp5加密解密
  5. ACM-ICPC 2018 南京赛区网络预赛 Lpl and Energy-saving Lamps (线段树:无序数组找到第一个小于val)
  6. A -- A. Quailty and Playing Cards 模拟 + 思考
  7. Python 2.x和3.x不同点
  8. Storm概念学习系列之storm-starter项目(完整版)(博主推荐)
  9. Python踩坑之旅其一杀不死的Shell子进程
  10. Json数组对象和对象数组