前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java设计模式--单例模式(代码详解懒汉、饿汉模式)

Java设计模式--单例模式(代码详解懒汉、饿汉模式)

作者头像
RAIN7
发布2022-04-17 11:07:05
4770
发布2022-04-17 11:07:05
举报

文章目录

设计模式-单例模式

啥是单例模式?

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

1.在类中就创建实例,只创建一个实例

2.类外如果想要调用这个对象必须调用getInstance方法获取实例,好处是减少了创建对象、销毁对象的开销

3.获取实例只能获取到类提供的唯一实例

懒汉模式

解释一下懒汉,懒汉就是懒加载,在类加载的时候不会去创建实例,在第一次调用的时候才会创建实例。

代码语言:javascript
复制
public class Singleton {

/**
* 以下是懒汉模式的代码
*/

    // 会产生线程安全问题,使用双重校验锁来保证安全

    private static Singleton instance = null;
  
   // 类加载过程不创建实例,实例设置为null

    public Singleton() {
    }

    public static Singleton getInstance(){
    // 第一次调用该类才会创建实例
        if(instance==null){
            return instance = new Singleton();
        }
    // 其后每次调用实例都使用上面创建的实例
        return instance;
    }

}

好处: 只有调用资源的时候才会创建实例,所以节约了资源。

坏处:懒汉模式会带来线程安全问题

如果多个线程同时获取实例,都是第一次获取,对执行 if(instance==null) 这个语句中的new实例,所以会创建出多个实例来。

怎么解决线程安全问题?

1.使用双重校验锁

第一个if(instance==null)

先判断实例是否存在,不存在再加锁

第二个if(instance==null)

当多线程都是第一次调用该对象的时候,只有一个线程能够进入,避免创建多个对象

代码语言:javascript
复制
 public static Singleton getInstance(){
        if (instance==null) { // 先判断实例是否存在,不存在再加锁
            synchronized (Singleton.class) {
                if(instance==null){// 多线程情况下,只有一个能进入,避免创建多个对象。
                    return instance = new Singleton();
                }
            }
        }
        return instance;
    }
2.volatile 修饰实例对象,禁止指令重排序
代码语言:javascript
复制
 private volatile static Singleton instance = null;

Instance = new Singleton 这段代码其实分成三步骤

1.为 new Singleton 分配内存空间

2.初始化对象实例

3.Instance 变量指向这块内存地址

初始化时间有点慢,所以JVM指令重排,顺序变了1->3->2,在单线程的情况下没啥问题,但是如果在多线程的情况下,第一个线程进去了,执行了1-3,这个时候第二个线程一个 实例不为null,直接返回了没有初始化 的实例对象,明显产生了线程安全问题。

所以使用 volatile 禁止指令重排。

线程安全的懒汉模式

代码语言:javascript
复制
public class Singleton {

    /**
 * 以下是懒汉模式的代码
 */

    // 会产生线程安全问题,使用双重校验锁来保证安全,使用volatile禁止指令重排序

    private volatile static Singleton instance = null;

    public Singleton() {
    }

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

}

饿汉模式

理解饿汉,因为太饿了,所以一拿到东西就想吃,这里就是类加载的过程就直接创建唯一实例。

好处:没有线程安全问题

坏处:不像懒汉模式调用才创建实例,这个是类加载就创建实例,所以如果一直没调用,也得创建实例浪费资源。

代码语言:javascript
复制
public class Singleton {
    private static Singleton instance = new Singleton();

    public Singleton() {
    }
    // 调用方法获取实例,只有读,所以没有线程安全问题
    public static Singleton getInstance(){
        return instance;
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 设计模式-单例模式
    • 懒汉模式
      • 怎么解决线程安全问题?
      • 线程安全的懒汉模式
    • 饿汉模式
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档