单例模式 (懒汉,饿汉,双重校验锁)

单例模式

什么是单例模式?

 单例保证一个对象JVM中只能有一个实例,常见单例懒汉式、饿汉式

 什么是懒汉式,就是需要的才会去实例化,线程不安全。

 什么是饿汉式,就是当class文件被加载的时候,初始化,天生线程安全。

 懒汉式 代码 

package designpatterns23.singleton;

/**
 * 单例模式的作用:保证一个类在项目中有且只能有一个实例
 * 在调用的时候在去初始化天生线程是不安全的
 * Created by lizhen on 2018/1/30.
 */
public class Singleton {
    private static Singleton singleton;

    /**
     * 构造方法私有化,防止在外部进行new
     */
    private Singleton() {

    }

    /**
     * 此方法是线程不安全的
     * 提供一个对外的方法获取singleton的实例
     *
     * @return singleton实例
     */
    public static Singleton getSingleton() {
        if (null == singleton) {
            singleton = new Singleton();
        }
        return singleton;
    }

   }

饿汉式线程 安全代码  

package designpatterns23.singleton;

/**
 * 单例模式的作用:保证一个类在项目中有且只能有一个实例
 * 在调用的时候在去初始化天生线程是不安全的
 * Created by lizhen on 2018/1/30.
 */
public class Singleton {
    private static Singleton singleton;

    /**
     * 构造方法私有化,防止在外部进行new
     */
    private Singleton() {

    }

   

    /**
     * 懒汉式修改为线程安全的方法
     * 缺点:加入锁影响效率
     *
     * @return
     */
    public static Singleton getSingleton2() {
        if (null == singleton) {
            //第一次同时进入判断的有可能有两个线程,所以在此处加入同步锁,相对于在方法上加入锁,提高了效率
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }

  
}




饿汉式 代码

package designpatterns23.singleton;

/**
 * 单例模式之饿汉式
 * 在加载的时候就已经初始化了,天生线程安全
 * Created by lizhen on 2018/1/30.
 */
public class Singleton1 {
    /**
     * 利用静态的关键字,类一加载便去初始化此类
     */
    private static Singleton1 singleton1 = new Singleton1();

    /**
     * 构造方法私有化
     */
    private Singleton1 (){

    }

    /**
     * 提供一个对外获取此类的方法
     * @return 此类的实例
     */
    public  static  Singleton1 getSingleton1(){
        return  singleton1;
    }
}

 双重校验锁

关于volatile关键字的使用,我有一篇专门关于讲解这个关键字的博客以及关于java内存模型的知识,大家可以看一下这一篇
http://mp.blog.****.net/postedit/79043326

package designpatterns23.singleton;

/**
 * 单例模式的作用:保证一个类在项目中有且只能有一个实例
 * 单例模式之懒汉式 ----双重校验锁
 * 在调用的时候在去初始化天生线程是不安全的
 * Created by lizhen on 2018/1/30.
 */
public class Singleton {
   
    /**
     * 构造方法私有化,防止在外部进行new
     */
    private Singleton() {

    }

    /**
     * 一般我们用双重校验锁的时候需要使用volatile关键字
     * volatile 是关于java内存模型相关的知识,只能保证可见性,但不能保证原子性
     */
   
private volatile static Singleton singleton;
/** * 双重校验锁模式 * * @return singleton 实例; */ public static Singleton getSingleton3() { if (singleton == null) { synchronized (Singleton.class) { /** * 为什么还要重新判断一下呢? * 因为同时等待锁的有可能有多个线程,当第一线程释放锁之后,后面的线程得到锁就可以进入这个方法 * 这时如果不进行判断的话很有可能就会创建多个实例. */ if (singleton == null) { singleton = new Singleton(); } } } return singleton; }}
我们看一下效果
单例模式 (懒汉,饿汉,双重校验锁)