单例模式总结

Reference

[1] http://jiangzhengjun.iteye.com/blog/652440

[2] http://blog.sina.com.cn/s/blog_6ee97c580100opvp.html

[3] http://javarevisited.blogspot.co.uk/2014/05/double-checked-locking-on-singleton-in-java.html

[4] https://www.hollischuang.com/archives/2498

单例类的特点:
1、单例类在整个系统中只能有一个实例
2、单例类必须自己创建自己的实例
3、单例类必须系统中其他对象提供这个实例

单例类的优点:

(1) 控制资源的使用,通过线程同步来控制资源的并发访问。
(2)控制实例的产生数量,达到节约资源的目的。
(3)作为通信的媒介,数据共享。他可以在不建立直接关联的条件下,让多个不相关的两个线程或者多个进程之间实现通信。

单例类实用举例:Windows的任务管理器,打不开两个。 网站的计数器,不然很难实现同步。   数据库连接池的设计

饿汉模式(非延迟加载)

在类加载时就立即创建对象。优点时没有加锁,执行效率高。缺点是类加载时就初始化,浪费内存。

public class SingletonOne {
  //Create instance when the class load.
  private static final SingletonOne m_instance = new SingletonOne();
  //此处写成私有方法可以防止用户在外面用new方法来产生。
  private SingletonOne(){}

  public static SingletonOne getInstance(){
     return m_instance;
  }
}

懒汉模式(同步延迟加载)

Lazy Load, 只在外部对象第一次请求实例的时候才会去创建,优点是第一次调用才会初始化,避免内存浪费。缺点是必须加锁synchronized才能保证单例。

public class SingletonTwo {
  private static SingletonTwo m_getInstance = null;

  //此处写成私有方法可以防止用户在外面用new方法来产生。
  private SingletonTwo(){
  
  }
  //synchronized可以保证线程安全
  public synchronized static SingletonTwo getInstance(){
     //When invoke the instance then create instance.
     if (m_getInstance == null){
        m_getInstance = new SingletonTwo();
     }
     return m_getInstance;
  }
}

双重检测同步延迟加载 

为处理原版同步延迟加载方式瓶颈问题,我们需要对 instance 进行第二次检查,目的是避开过多的同步(因为这里的同步只需在第一次创建实例时才同步,一旦创建成功,以后获取实例时就不需要同获取锁了)。

所谓双重检查加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样一来,就只需要同步一次了,从而减少了多次在同步情况下进行判断所浪费的时间。

 双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。
注意:在Java1.4及以前版本中,很多JVM对于volatile关键字的实现有问题(no happens-brfore),会导致双重检查加锁的失败,因此双重检查加锁的机制只能用在Java5及以上的版本。

public class Singleton {
    private volatile static Singleton instance = null;
    private Singleton(){
    }
    public static  Singleton getInstance(){
        //先检查实例是否存在,如果不存在才进入下面的同步块
        if(instance == null){
            //同步块,线程安全的创建实例
            synchronized(Singleton.class){
                //再次检查实例是否存在,如果不存在才真的创建实例
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

改进型懒汉模式

内部类只有在外部类被调用才加载,产生SINGLETON实例,又不用加锁,此模式有上述俩模式的优点,屏蔽了他们的缺点,是比两者都好的单例模式。

public class Singleton{
    private Singleton(){}
    public static Singleton getInstance(){ return Holder.SINGLETON;}
    private static class Holder{//内部类
        private static final Singleton SINGLETON= new Singleton();
    }
}

ENUM单例模式

 线程安全而且代码最为简单

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
} 
原文地址:https://www.cnblogs.com/codingforum/p/6943176.html