码迷,mamicode.com
首页 > 其他好文 > 详细

【读书】二、单例模式

时间:2016-02-20 00:37:40      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:

特点:

1.构造函数不外放,一般都是private

2.通过暴露一个public的静态方法或者枚举来返回一个单例对象

3.在多线程环境下面,确保单例类对象有且只有一个

4.确保单例类对象再反序列化时候不会重新构建对象

 

懒汉模式:

 1 public class Singleton{
 2     private static Singleton instance;
 3     //1.构造函数不对外开放
 4     private Singleton{
 5     }
 6     //2.通过一个静态方法来返回单例类对象
 7     //3.加了synchronized,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized修饰的方法或者代码块。
 8     //也就是getInstance是一个同步方法,保证多线程下对象唯一
 9     public static synchronized Singleton getInstance(){
10         if(instance == null){
11             instance = new Singleton();
12         }
13         return instance;
14     }
15     
16 }

 

优点:需要时候才实例化,节约资源

缺点:每次调用getInstance()都要同步,造成不必要的同步开销

 

Double checkLock实现单例:

 1 public class Singleton{
 2     private volatile static Singleton singleton;
 3     private Singleton (){}
 4     public static Singleton getInstance() {
 5         //第一层判空是为了避免不必要的同步
 6         //从而只有第一次的时候才会加锁,之后就不会加锁
 7         if (singleton == null) {
 8             synchronized (Singleton.class) {
 9                 if (singleton == null) {
10                     //第二层判空是为了在null的情况下创建实例
11                     singleton = new Singleton();
12                 }
13             }
14         }
15         return singleton;
16     }
17 }

注意DCL是有问题的:

singleton = new Singleton();

这句并不是原子操作,它可以拆分三件事:

(1).给Singleton的实例分配内存

(2).调用Singleton的构造函数,创建对象

(3).将singleton的对象指向内存分配的空间

但是,由于Java编译器允许处理器乱序执行,以及JDK1.5之前JVM中Cache,寄存器以及主内存回写顺序的规定,(2)与(3)的顺序不是固定的,

所以可能执行顺序是123,也可能是132

如果是132,那么此时比如A线程执行到13,还未执行2,此时B线程也在执行,检查singleton非空,直接使用,就会出错

所如果是JDK1.5以及之后的版本,加上Volatile关键字:

private volatile static Singleton singleton;

这样就可以保证singleton对象每次都是从主内存中读取。

 

静态内部类单例模式:

 1 public class Singleton{
 2     private Singleton{}
 3     public static Singleton getInstance(){
 4         return SingletonHolder.sInstance;
 5     }
 6     /*
 7     静态内部类
 8     */
 9     private static class SingletonHolder{
10         private static final Singleton sInstance = new Singleton();
11     }
12 }

优点:只有第一次调用getInstance才会导致sInstance被初始化,第一次调用时候会导致虚拟机加载SingletonHolder类,

这样能保证线程安全,也能保证单例对象唯一,还能延迟单例实例化

 

枚举单例:

1 public enum SingletonEnum{
2     INSTANCE;
3 }

优点:线程安全,唯一,还能防止反序列化。

 

破坏单例对象的唯一:

1.反射

2.序列化与反序列化

 http://www.hollischuang.com/archives/1144

 

【读书】二、单例模式

标签:

原文地址:http://www.cnblogs.com/wufeng0927/p/5202466.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!