java设计模式——单例模式(三)
容器单例模式
之前学习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的单例模式。
java设计模式——单例模式(三)的更多相关文章
- Java设计模式(三) 抽象工厂模式
原创文章,同步发自作者个人博客,转载请注明出处 http://www.jasongj.com/design_pattern/abstract_factory/ 抽象工厂模式解决的问题 上文<工厂 ...
- Java设计模式の单例模式
-------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...
- JAVA设计模式-单例模式(Singleton)线程安全与效率
一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...
- Java设计模式 - - 单例模式 装饰者模式
Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...
- java设计模式单例模式 ----懒汉式与饿汉式的区别
常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...
- 【设计模式】Java设计模式 - 单例模式
[设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...
- Java 设计模式 —— 单例模式
1. 概念: 单例模式是一种常用的软件设计模式.核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果 ...
- Java设计模式 - 单例模式 (懒汉方式和饿汉方式)
概念: Java中单例模式是一种常见的设计模式,单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的写法有好几种,这 ...
- java设计模式——单例模式(一)
一. 定义与类型 定义:保证一个类仅有一个实例,并提供一个全局访问点 类型:创建型 二. 适用场景 想确保任何情况下都绝对只用一个实例 三. 优缺点 优点: 在内存里只有一个实例,减少了内存开销 可以 ...
随机推荐
- git教程3-分支
https://git-scm.com/book/zh/v1/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E7%AE%A1%E7%90%86 ...
- JSON长度
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Predicate; import net.minidev.json.J ...
- 利用git reflog找回错误的重置
在开发中经常需要reset分支,如果在reset前没有记住分支指向的提交ID,想要重置回原来的提交恐怕大多数开发者是重新拉取远程版本库,再rebase分支.但如果连不上远程版本库或没有远程版本怎么办呢 ...
- Django---登录(含随机生成图片验证码)、注册示例讲解
登录(验证码).注册功能具体代码 # urls.py from django.contrib import admin from django.urls import path from app01 ...
- 【ACM】喷水装置
喷水装置(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以 ...
- map系统学习
映射map又称字典,表,或者查找表,其元素是由key和value两个分量组成的对偶(key,value). key是键,value是与键key相关联的映射值,这样的元素又称“关联”.key和value ...
- Fence Repair (二叉树求解)(优先队列,先取出小的)
题目链接:http://poj.org/problem?id=3253 Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Sub ...
- C - Watchmen
题目链接:https://vjudge.net/contest/237394#problem/C Watchmen are in a danger and Doctor Manhattan toget ...
- CentOS 7 iptables 开放8080端口
# 安装iptables-services [root@localhost bin]# yum install iptables-services [root@localhost bin]# /bin ...
- 牛客网Java刷题知识点之构造函数可以调用一般函数,但是一般函数不可以直接调用构造函数
不多说,直接上干货! 通过 牛客网Java刷题知识点之构造函数是什么.一般函数和构造函数什么区别呢.构造函数的重载.构造函数的内存图解 我们对构造函数有了一个比较清楚的认识,当我们在创建对象时,我们会 ...