单例模式的实现方式(懒汉式、饿汉式、双重判断、静态内部类)

目录树如图:

写在最前:

如下五个文件分别对应:
1.(懒汉式)最经典的单例模式(多线程时有概率会出现问题)

2.(懒汉式、饱汉式)使用同步关键字进行改进,就是将getXXX方法进行同步化,
    这样就可以防止多线程引发的问题了,可是执行效率低

3.(饿汉式)直接初始化单例对象 private static Singleton uniqueInstance= new Singleton();
    这样在多线程的情况下也能保证只初始化一次

4.(双重检测)双重判断获取单例,先将其赋予null,在访问的时候在进行赋值,而且只进行一次,提高了效率

5.(静态内部类实现)

总结:
    一般采用饿汉式(3),若对资源十分在意可以采用静态内部类(5),不建议采用懒汉式(1、2)及双重检测(4)

A01_原始懒汉式( 线程不安全 )

/**
 * 经典单例模式,类的实例只有一个
 * 介绍:单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。
 * 通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
 * 适用情况:比如java中的线程池,数据库连接池,和一些硬件设备,比如打印机等,这些资源的数量是一定的,
 * 所以设计的时候就可以适用单例模式的思想。
 *
 * 如下是 懒汉式 的范例,但是其有线程安全问题,所以使用双重判断,也就是如下的A04___方式
 *
 */
public class A01_Singleton {
    //1.定义一个静态变量存储当前类的对象
    private static A01_Singleton uniqueInstance= null;
    //2.私有化构造方法
    private A01_Singleton() {}
    //3.定义一个静态方法返回类的对象
    public static A01_Singleton getInstance() {
        if(uniqueInstance==null) {
            uniqueInstance = new A01_Singleton();
        }
        return uniqueInstance;
    }
}

/**
 *
 * 经典单例模式分析:如果是在单线程的情况下经典单例模式没有什么问题,实现也比较简单,
 * 但在多线程的情况下会出现问题,比如有两个线程A和B,线程是通过时间片来切换的,
 * 一种极端的情况下,线程A和B都执行了if(uniqueInstance==null) 发现为空,
 * 然后各自创建了一个对象,这样就会出现问题.
 *
 */

A02_使用同步的懒汉式 ( 线程安全的懒汉式 )

/**
 * 经典单例模式,类的实例只有一个
 *
 * 经典单例模式分析:如果是在单线程的情况下经典单例模式没有什么问题,实现也比较简单,
 * 但在多线程的情况下会出现问题,比如有两个线程A和B,线程是通过时间片来切换的,
 * 一种极端的情况下,线程A和B都执行了if(uniqueInstance==null) 发现为空,
 * 然后各自创建了一个对象,这样就会出现问题.
 *
 * 改进一:使用同步关键字 (懒汉式、饱汉式)
 *
 */
public class A02_Singleton {
    private static A02_Singleton uniqueInstance= null;
    private A02_Singleton() {}
    //改进:使用synchronized关键字来保证单例.
    public static synchronized A02_Singleton getInstance() {
        if(uniqueInstance==null) {
            uniqueInstance = new A02_Singleton();
        }
        return uniqueInstance;
    }
}
/**
 * 使用同步关键字来保证单例的话会消耗很多资源,如果需要获取单例对象的操作很少,
 * 这种方法也可以使用,但当获取单例对象的操作很多时这样会极大的降低运行效率。
 *
 * 优点:资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法
 *
 * 缺点:第一次加载时不够快,多线程使用不必要的同步开销大
 */

A03_饿汉式【推荐的方式】

/**
 * 经典单例模式,类的实例只有一个
 *
 * 使用同步关键字来保证单例的话会消耗很多资源,如果需要获取单例对象的操作很少,这种方法也可以使用,
 * 但当获取单例对象的操作很多时这样会极大的降低运行效率。
 *
 *   改进二:直接初始化单例对象(也就是 饿汉式 的创建方式,直接初始化单例对象)【推荐使用该创建方式】
 */
public class A03_Singleton {
    //直接初始化单例,这样在多线程的情况下也能保证只初始化一次
    private static A03_Singleton uniqueInstance= new A03_Singleton();
    private A03_Singleton() {}
    public static A03_Singleton getInstance() {
        return uniqueInstance;
    }
}
/**
 *
 * 优点 	1.线程安全
 *      2.在类加载的同时已经创建好一个静态对象,调用时反应速度快
 *
 * 缺点 	资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),
 *      那么这个实例仍然初始化
 *
 */

A04_双重判断获取单例

/**
 * 经典单例模式,类的实例只有一个
 *
 *    改进三:双重判断获取单例
 */
public class A04_Singleton {
    private static volatile A04_Singleton uniqueInstance= null;
    private A04_Singleton() {}
    //使用双重判断来保证单例并保证效率
    public static A04_Singleton getInstance() {
        if(uniqueInstance==null) {
            synchronized (A04_Singleton.class) {
                if(uniqueInstance==null) {
                    uniqueInstance = new A04_Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}
/**
 * 这种方法存储单例对象的属性要设置成volatile来保证可见性,然后先判断一次,之后是一个类锁,
 * 类锁会保证线程安全,在类锁中再判断一次,这样之后再第一次判断的时候初始化一次,
 * 之后不会再执行类锁中的代码,所以提高了效率
 *
 * 优点:资源利用率高,不执行getInstance()就不被实例,可以执行该类其他静态方法
 *
 * 缺点:第一次加载时反应不快,由于java内存模型一些原因偶尔失败
 */

A05_静态内部类实现单例【 次推荐 】

/**
 * 静态内部类实现
 */
public class A05_Singleton {
    private A05_Singleton() {}

    private static class SingletonHelp {
        static A05_Singleton instance = new A05_Singleton();
    }

    public static A05_Singleton getInstance() {
        return SingletonHelp.instance;
    }
}

/**
 * 优点:资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法
 *
 * 缺点:第一次加载时反应不够快
 */

写在最后( 同写在最前 )

如下五个文件分别对应:
1.(懒汉式)最经典的单例模式(多线程时有概率会出现问题)

2.(懒汉式、饱汉式)使用同步关键字进行改进,就是将getXXX方法进行同步化,
    这样就可以防止多线程引发的问题了,可是执行效率低

3.(饿汉式)直接初始化单例对象 private static Singleton uniqueInstance= new Singleton();
    这样在多线程的情况下也能保证只初始化一次

4.(双重检测)双重判断获取单例,先将其赋予null,在访问的时候在进行赋值,而且只进行一次,提高了效率

5. 静态内部类实现

总结:
    一般采用饿汉式(3),若对资源十分在意可以采用静态内部类(5),不建议采用懒汉式(1、2)及双重检测(4)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值