设计模式之单例模式

一、单例模式是什么?

单例模式(Singleton Pattern)是最简单的设计模式之一.

单例模式,顾名思义就是只有一个实例,并且自己负责创建自己的对象,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

二、单例模式的几种实现方式

1.懒汉式 线程不安全

代码如下(示例):

/**
 * 懒汉模式
 * 只有用到的时候才会创建,用到的时候才会检测是否已经实例化,如果有则返回,没有则进行初始化实例.
 */
public class Idler {
    private static Idler instance;

    private Idler() {
    }

    public static Idler getInstance() {
        if (instance == null) {
            instance = new Idler();
        }
        return instance;
    }
}

优点:
1、在获取实例的方法中,进行实例的初始化,节省系统资源

缺点:
1、每次获取实例都要进行非空检查,系统开销大
2、非线程安全,当多个线程同时访问getInstance()时,可能会产生多个实例

2. 懒汉式 线程安全

代码如下(示例):

/**
 * 懒汉模式
 * 只有用到的时候才会创建,用到的时候才会检测是否已经实例化,如果有则返回,没有则进行初始化实例.
 * 此锁每次调用 getInstance()方法都要加锁 效率极低
 */
public class Idler {
    private static Idler instance;

    private  Idler() {
    }

    public static synchronized Idler getInstance() {
        if (instance == null) {
            instance = new Idler();
        }
        return instance;
    }
}

优点:
1、在获取实例的方法中,进行实例的初始化,节省系统资源
2、线程安全但影响效率

缺点:
1、必须加锁 synchronized 才能保证单例,但加锁会影响效率。

3.饿汉式

代码如下(示例):


/**
 * 饿汉模式
 * 实例在类初始化的时候就已经建好了,不管你有没有用到,都先建好了再说。
 */
public class Hungry {
    private static Hungry instance = new Hungry();

    private Hungry() {
    }

    public static Hungry getInstance() {
        return instance;
    }

}

优点:
1、线程安全
2、获取实例速度快

缺点:
1、类加载即初始化实例
2、内存浪费

4.双检索(双重检索模式)

代码如下(示例):

/**
 *双检锁(双重检查锁)
 * synchronized 关键字 没有实例化的时候才会进行加锁.比懒汉式 加方法锁 效率要高.
 * volatile(必加)
 * 
 * 当A/B 两线程同时执行getInstance方法时,A先进入后会加锁,B则等待.
 * 此时A将instance实例化后会同步到主线程,A执行完后会.B会向主线程拷贝instance实例,
 * 但此时实例已被A修改.此时instance!=null,拿到后也不会在进行新建实例
 */
public class DoubleCheck {
	//volatile 必加 保证可见性和禁止指令重排序
    private volatile static DoubleCheck instance;

    private DoubleCheck() {
    }

    public static DoubleCheck getInstance() {
        if (instance == null) {
            synchronized (DoubleCheck.class) {
            	if(instance==null){
                instance = new DoubleCheck();
                }
            }
        }
        return instance;
    }


}

双检索:安全且在多线程情况下能保持高性能,但略复杂。

volatile关键字:

读:每当子线程某一语句要用到volatile变量时,都会从主线程重新拷贝一份,这样就保证子线程的会跟主线程的一致。

写: 每当子线程某一语句要写volatile变量时,都会在读完后同步到主线程去,这样就保证主线程的变量及时更新。


总结

 本文首先介绍了单例模式的定义和结构。传统的饿汉式单例无论在单线程还是多线程环境下都是线程安全的,但是传统的懒汉式单例在多线程环境下是非线程安全的。双检锁模式就是懒/饿 优点结合在一起的. 从而发现如果学习并发编程的话volatile关键词还是非常重要的.
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值