设计模式(java)1——单例模式
2015-07-11 16:24
507 查看
如果要保证系统里一个类最多只能存在一个实例时,我们就需要单例模式。例如:缓存池,数据库连接池,线程池,一些应用服务实例等。
1、懒汉模式——实现懒加载但线程不安全
2、懒汉模式——实现懒加载,线程安全但效率低
效率低。锁住整个方法,上述代码中的一次锁住了一个方法, 这个粒度有点大。只需锁住new 语句。
3、双重校验锁。实现懒加载,线程安全,且效率较第二种高(推荐掌握)
4、饿汉模式——线程安全,但是无懒加载。
上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,
当系统中这样的类较多时,会使得启动速度变慢 。现在流行的设计都是讲“延迟加载”,我们可以在第一次使用的时候才初始化第一个该类对象。所以这种适合在小系统。
5、饿汉模式(变种)——线程安全,但是无懒加载。
本质上与第四中一样。
6、静态内部类——线程安全,实现懒加载。(推荐)
这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),
而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。 想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。
7、枚举——实现线程安全、懒加载、防止反序列化重新创建新的对象。本质上是最佳实现方式。
讨论:
单例模式与垃圾回收
当一个单例的对象长久不用时,不会被jvm的垃圾收集机制回收。
/article/1358576.html
参考博客:
/article/4029821.html
/article/1358575.html
1、懒汉模式——实现懒加载但线程不安全
package singleton; //懒汉模式(线程不安全) public class Singleton1 { private static Singleton1 instance; private Singleton1() { } public static Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } }
2、懒汉模式——实现懒加载,线程安全但效率低
public class Singleton2 { private static Singleton2 instance; private Singleton2() { } public static synchronized Singleton2 getInstance() { if (instance == null) { instance = new Singleton2(); } return instance; } }
效率低。锁住整个方法,上述代码中的一次锁住了一个方法, 这个粒度有点大。只需锁住new 语句。
3、双重校验锁。实现懒加载,线程安全,且效率较第二种高(推荐掌握)
public class Singleton7 { private volatile static Singleton7 singleton; private Singleton7() { } public static Singleton7 getInstance() { if (singleton == null) { synchronized (Singleton7.class) { if (singleton == null) { singleton = new Singleton7(); } } } return singleton; } }
4、饿汉模式——线程安全,但是无懒加载。
public class Singleton3 { private static Singleton3 instance = new Singleton3(); private Singleton3() { } public static Singleton3 getInstance() { return instance; } }
上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,
当系统中这样的类较多时,会使得启动速度变慢 。现在流行的设计都是讲“延迟加载”,我们可以在第一次使用的时候才初始化第一个该类对象。所以这种适合在小系统。
5、饿汉模式(变种)——线程安全,但是无懒加载。
public class Singleton4 { private static Singleton4 instance = null; static { instance = new Singleton4(); } private Singleton4() { } public static Singleton4 getInstance() { return instance; } }
本质上与第四中一样。
6、静态内部类——线程安全,实现懒加载。(推荐)
public class Singleton5 { private static class SingletonHolder { private static final Singleton5 INSTANCE = new Singleton5(); } private Singleton5() { } public static final Singleton5 getInstance() { return SingletonHolder.INSTANCE; } }
这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),
而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。 想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。
7、枚举——实现线程安全、懒加载、防止反序列化重新创建新的对象。本质上是最佳实现方式。
public enum Singleton6 { INSTANCE; public void whateverMethod() { } }
讨论:
单例模式与垃圾回收
当一个单例的对象长久不用时,不会被jvm的垃圾收集机制回收。
/article/1358576.html
参考博客:
/article/4029821.html
/article/1358575.html
相关文章推荐
- 【Java】Java reflection
- SpringMVC视图解析器
- Java-IO流篇
- Java类加载器(一)
- eclipse安装android插件ADK
- Java中的(JDK5新特性)枚举10
- Rfc2898DeriveBytes解密如何通过java实现
- Java多线程基本概念
- Struts2 标签库与OGNL的使用
- JavaBean的相关知识
- java中把一句话或字符串内容反转输出
- java 单例模式
- AES加密时抛出java.security.InvalidKeyException: Illegal key size or def
- java基础之——DecimalFormat格式化数字
- Java-CyclicBarrier的简单例子
- 【j2ee spring】41、巴巴运动网的产品查询
- Struts2 改变语言状态
- 开源项目导入eclipse的一般步骤
- Struts2 文件下载
- Java 正则表达式详解