单例模式总结和应用
来源:互联网 发布:剑网三菊花插件dbm数据 编辑:程序博客网 时间:2024/06/06 05:51
单例模式(Singleton)
单例模式就是创建类的一种方式,保证该类仅有一个实例,该类可以向外部提供一个其实例的全局访问点。类自身维护实例,可以保证外部随时能够访问,并且能够防止实例化多个对象。
实现单例类的关键:
私有构造器;自身的私有的静态成员;公共的静态实例访问方法。
1. 实现方案
方案一
/** * 单例模式:方案一 */public class Singleton { // 将构造方法私有化,防止以new的方式创建实例 private Singleton() { } // 定义一个引用自身对象的属性,该属性为静态常量 private static final Singleton instance = new Singleton(); /** * 静态方法,返回该类的实例 * @return */ public static Singleton getInstance() { return instance; }}
该方法较为简单,而且获取的实例是静态常量,因此不存在线程安全问题,完全摒弃了synchronized造成的性能问题。然而,当该类被加载时,就会创建静态常量对象,并且该对象会一直占有内存,直到该类卸载,因此有些情况下会造成内存问题。
方案二
/** * 单例模式:方案二 */public class Singleton { // 将构造方法私有化,防止以new的方式创建实例 private Singleton() { } // 定义一个自身类型的静态变量 private static Singleton instance = null; /** * 静态方法,返回该类的实例 * @return */ public static Singleton getInstance() { // 判断该实例是否存在 if (null == instance) instance = new Singleton(); return instance; }}
方案二仅仅是基于内存的节省对方案一的改造,但是如果在多线程环境下,有可能会产生多个实例对象,因此不是线程安全的。
方案三
/** * 单例模式:方案三 */public class Singleton { // 将构造方法私有化,防止以new的方式创建实例 private Singleton() { } // 定义一个自身类型的静态变量 private static Singleton instance = null; /** * 静态方法,返回该类的实例 * 方法添加同步锁,防止多线程访问产生多个实例 * @return */ public synchronized static Singleton getInstance() { // 判断该实例是否存在 if (null == instance) instance = new Singleton(); return instance; }}
方案三在方案二的基础上为静态方法添加同步锁,以达到线程安全的要求。但是同步方法被频繁调用时,当然会存在效率问题。
方案四
/** * 单例模式:方案四 */public class Singleton { // 将构造方法私有化,防止以new的方式创建实例 private Singleton() { } // 定义一个自身类型的静态变量 private static Singleton instance = null; /** * 静态方法,返回该类的实例 * 方法内部添加同步块,不用每次调用方法都要获取同步锁 * @return */ public static Singleton getInstance() { // 判断该实例是否存在 if (null == instance) { // 如果不存在,才获取同步锁,如果存在则直接返回对象 synchronized(Singleton.class) { if (null == instance) { instance = new Singleton(); } } } return instance; }}
方案四改进了方案三,保证只有在必要的情况下,即当对象没有创建的时候才获取同步锁,如果对象已经存在,则直接返回即可,实现了高效并且线程安全。
方案四需要注意同步块中又进行了一次判断,原因是,如果当代码执行到第一次判断时,有可能另一个线程刚好创建了一个实例,因此,获取锁之后还要判断一次。
2. 应用举例
例如,在使用Jedis的时候,由于多线程下频繁使用,因此需要使用连接池来管理多个Jedis连接,而为了保证连接池只有一个,则需要采用单例模式,如果不用Spring来管理连接池,则需要使用单例模式:
/** * Redis连接池工具 */public class JedisPoolUtil { private static volatile JedisPool jedisPool = null; // 提供一个私有构造函数保证单例 private JedisPoolUtil() { } /** * 获取一个<tt>JedisPool</tt> * @return jedisPool 一个单例的{JedisPool} */ public static JedisPool getJedisPoolInstance() { if (null == jedisPool) { synchronized (JedisPool.class) { if (null == jedisPool) { JedisPoolConfig poolConfig = new JedisPoolConfig(); // poo2已经更改maxActive为maxTotal poolConfig.setMaxTotal(32); // pool2已经更改为maxWaitMillis poolConfig.setMaxWaitMillis(100 * 1000); jedisPool = new JedisPool(poolConfig, "0.0.0.0", 6379); } // if end } // synchronized end } // if end return jedisPool; } public static void release(JedisPool jedisPool) { Jedis jedis = null; try { jedis = jedisPool.getResource(); } finally { if (null != jedis) jedis.close(); } }}
0 0
- 单例模式总结和应用
- 单例和工厂模式应用
- 单例模式的写法和应用
- 单例模式介绍和应用
- 单例模式应用
- 单例模式应用
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 总结单例模式
- 单例模式总结
- 单例模式总结
- 单例模式总结
- 6.3.3 返回数组指针
- 算法导论复习(1) 插入排序
- Tree-----镜像树(101. Symmetric Tree)
- 安装
- 以太坊智能合约编程之菜鸟教程
- 单例模式总结和应用
- 以太坊区块链白皮书
- Thymeleaf 常用属性
- 漫画网站爬虫详解
- ORA-01504问题
- DSST折腾笔记(一):树莓派3上的移植
- 纯C++创建Windows窗体(理解WinMain()与WndProc())
- ORB-SLAM2
- unity三次样条曲线的简单实现