读书二单例模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了读书二单例模式相关的知识,希望对你有一定的参考价值。

特点:

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

 

以上是关于读书二单例模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式二单例模式

java设计模式之单例模式

Android框架设计模式——Singleton Method

[读书笔记] JavaScript设计模式: 单例模式

JavaScript设计模式与开发实践-读书笔记单例模式

设计模式比较