让类自己来承担创建自己仿佛的实例。所以一个虚拟机在经过投机之ClassLoader装载饿汉式实现单例类的下即便见面创一个好像的实例。

管一个像样才来一个实例,并提供一个访问它的大局访问点。

定义

保证一个接近就发生一个实例,并提供一个走访它的全局访问点。
Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的主意,让外部来拜会是近乎的唯一实例。

  • 饿汉式: private static Singleton uniqueInstance = new Singleton();
  • 懒汉式 private static Singleton uniqueInstance = null;

倘想操纵一个类就吃创造一个实例,那么重大之题目不怕是管创建实例的权能收回来,让类似自己来顶住创建好好像的实例,然后由是仿佛来供外部可以看这个类似实例的方法,这就是是单例模式之落实方式。

功能

单例模式是用来保管是看似以运作中只有见面被创造一个近似实例,另外,单例模式还提供了一个大局唯一访问是类似实例的访问点,就是getInstance方法。

单例模式的构造与兑现

图片 1

单例模式的结构图

Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,来外部来做客这类似的唯一实例。

  1. 私有化构造方法
  2. 提供静态的落实例的办法
  3. 概念存储实例的习性,因为要是于静态方法中使用,因此要长static修饰
  4. 兑现控制实例的创始

范围

Java里面实现的单例是一个虚拟机的范围。因为装载类的效力是虚拟机的,所以一个虚拟机在经友好之ClassLoader装载饿汉式实现单例类的上就是见面创一个看似的实例。
懒汉式单例有延期加载与缓存的思考

示范代码

优缺点

  • 懒汉式是一流的时刻换空间
  • 饿汉式是第一流的上空更换时间

未加一起的懒汉式是线程不安全的。比如,有三三两两个线程,一个凡线程A,一个是线程B,它们以调用getInstance方法,就可能引致出现问题。
-饿汉式是线程安全之,因为虚拟机保证单独会装一次于,在装载类的时刻是匪会见发出起的。

怎么样促成懒汉式的线程安全?
加上synchronized即可

public static synchronized Singleton getInstance(){}

可这样见面减低整个访问的快,而且每次都设判断。可以为此更检查加锁。

双重加锁机制,指的是:并无是每次上getInstance方法还亟需共同,而是先不一起,进入方式了后,先检查实例是否在,如果未有才登下的一块块,这是率先再度检查。进入同步块后,再次检查实例是否存在,如果无在,就以协同的景况下创造一个实例。这是亚双重检查。

再也加锁机制的实现会晤使一个要害字volatile,它的意是:被volatile修饰的变量的值,将未会见受地面线程缓存,所有对该变量的读写都是直操作共享内存,从而确保多独线程能是的拍卖该变量。

/**
 * 双重检查加锁的单例模式
 * @author dream
 *
 */
public class Singleton {

    /**
     * 对保存实例的变量添加volitile的修饰
     */
    private volatile static Singleton instance = null;
    private Singleton(){

    }

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

}

相同种更好的单例实现方式

public class Singleton {

    /**
     * 类级的内部类,也就是静态类的成员式内部类,该内部类的实例与外部类的实例
     * 没有绑定关系,而且只有被调用时才会装载,从而实现了延迟加载
     * @author dream
     *
     */
    private static class SingletonHolder{
        /**
         * 静态初始化器,由JVM来保证线程安全
         */
        private static final Singleton instance = new Singleton();
    }

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

    }

    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}

因《高效Java第二本》中的传道,单元素的枚举类型已成为实现Singleton的超级方法。

package example6;

/**
 * 使用枚举来实现单例模式的示例
 * @author dream
 *
 */
public class Singleton {

    /**
     * 定义一个枚举的元素,它就代表了Singleton的一个实例
     */
    uniqueInstance;

    /**
     * 示意方法,单例可以有自己的操作
     */
    public void singletonOperation(){
        //功能树立
    }
}

懒汉模式

所谓懒汉模式,既然懒,那么在创建对象实例时就毫无着急,在就要动用对象实例时才会创,在装载对象时未见面创建对象实例。

package com.liuhao.designpattern.singleton;

/**
 * 单例模式懒汉模式
 * 
 * @author liuhao
 * 
 *         2015年7月17日
 */
public class SingletonLazy {
    // 4. 定义一个变量来存储创建好的类实例
    // 5. 因为要在静态方法中使用,因此要加上static修饰
    private static SingletonLazy instance = null;

    // 1. 构造方法私有化,好在内部控制创建实例的数目
    private SingletonLazy() {
    }

    // 2. 定义一个方法为客户端提供类实例
    // 3. 这个方法需要定义成类方法,也就是
    public static SingletonLazy getInstance() {
        // 6. 判断存储实例的变量是否有值
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }

    private String singletonData;// 单例可以有自己的属性

    /**
     * 获取属性的值
     * 
     * @return 属性的值
     */
    public String getSingletonData() {
        return singletonData;
    }

    /**
     * 单例可以有自己的操作方法
     */
    public void singletonOperation() {

    }
}

本质

操纵实例数量

饿汉模式

所谓饿汉模式,就是于创建对象实例时较匆忙,在装载类的下就会创建对象实例。

package com.liuhao.designpattern.singleton;

/**
 * 单例模式饿汉模式
 * 
 * @author liuhao
 * 
 *         2015年7月17日
 */
public class SingletonHungry {
    // 4. 直装载类的时候就会创建对象实例,只创建一次
    private static SingletonHungry instance = new SingletonHungry();

    // 1. 构造方法私有化,好在内部控制创建实例的数目
    private SingletonHungry() {
    }

    // 2. 定义一个方法为客户端提供类实例
    // 3. 这个方法需要定义成类方法,也就是
    public static SingletonHungry getInstance() {
        // 5. 直接使用以及创建好的实例
        return instance;
    }

    private String singletonData;// 单例可以有自己的属性

    /**
     * 获取属性的值
     * 
     * @return 属性的值
     */
    public String getSingletonData() {
        return singletonData;
    }

    /**
     * 单例可以有自己的操作方法
     */
    public void singletonOperation() {

    }
}

何时选用单例模式

当得控制一个看似的实例只能有一个,而且客户只能于一个大局访问点访问它经常,可以选用单例模式,这些成效恰好是单例模式一旦解决的题材。

其他

单例模式之界定

时Java实现之单例是一个虚拟机范围之,因为装载类的法力是虚拟机的,所以一个虚拟机在经友好之ClassLoader装载饿汉模式实现单例时即便见面创造一个近似的实例。

从而要一个虚拟机里面来成千上万个ClassLoader,而这些ClassLoader都装有类的讲话,就会发生多只实例。

单例模式的调用顺序

  • 懒汉模式

图片 2

单例模式之调用顺序

  • 饿汉模式

图片 3

单例模式的调用顺序

反映的局部思考

  • 缓加载
    懒汉模式面临,一开始没加载所需要的资源还是数额,一直顶及即将用了才加载,即所谓的“延迟加载”。

  • 缓存
    当一些资源或数量为反复之以,而且它们是储存于网外部的(如数据库、硬盘),那么每次操作都要打数据库获取,速度会充分缓慢,操作性能问题。

一个简约的方就是管这些数据缓存到内存中,每次操作的时段先到内存里找,若发生则一直采用;若果没有更获其并安装到缓存中。

缓存是同等栽典型的半空中换取时间的方案。

线程安全

  1. 切莫加同的懒汉模式是线程不安全的。比如,有线程A、B同时调用getInstance方法,那便可能致出现问题,如图。
![](http://hoxis-github-io.qiniudn.com/150717-singleton-threadconflict.png)
懒汉模式线程冲突
  1. 怎兑现懒汉模式之线程安全

    1. 累加要字synchronized,如下

    public static synchronized SingletonLazy getInstance() {}
    
    1. 重新检查加锁。不是在每次上getInstance时还需要并,而是先不同步,进入艺术后,先反省实例是否留存。如果不存在才进入下的旅块,这是率先又检查。进入同步块后,再次检查实例是否是,如果不设有,就在一齐的情状下创造一个实例,这是第二复检查。
      再次检查加锁机制的落实用采取volatile主要字,被其修饰的变量的值将未会见为地面线程缓存,所有对该变量的读写都是一直操作共享内存,从而确保多独线程能够科学的拍卖该变量。
      实际实现:

    public static SingletonVolatile getInstance() {
        // 检查实例是否存在,不存在则进入到同步块
        if (instance == null) {
            // 同步块,线程安全地创建实例
            synchronized (SingletonVolatile.class) {
                // 再次检查实例是否存在,不存在则真正的创建实例
                if (instance == null) {
                    instance = new SingletonVolatile();
                }
            }
        }
        return instance;
    }
    

    这种实现方式既可兑现线程安全,同时为无见面针对性能造成极其可怜之熏陶。

  2. 饿汉模式是线程安全的。

相关文章