java单例模式学习笔记

1、单例模式定义

确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。比如:线程池、缓存、日志对象。

2、单例模式的特点

①构造函数私有化:private
②在类中创建一个本类对象
③提供一个方法可以获取到该对象

3、单例模式的种类

(1)懒汉式——线程不安全
(2)饿汉式——天生线程安全

懒汉式单例——线程不安全,需要我们改造成线程安全

/**
 * 懒汉式单例类——线程不安全
 * 在第一次调用的时候实例化自己
 */
public class DanLi {

   //通过将构造方法限定为private避免了类在外部被实例化,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,
    // 只有通过该类提供的静态方法getDanLi来得到该类的唯一实例
    private DanLi() {
    }

    //创建静态对象
    private static DanLi danLi = null;

    //在该类内提供一个静态方法
    // 当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用。
    public static DanLi getDanLi() {
        if (danLi == null) {
            danLi = new DanLi();
        }
        return danLi;
    }
}

以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全。

方式一:在getInstance方法上加同步

public static synchronized DanLi getDanLi() {
        if (danLi == null) {
            danLi = new DanLi();
        }
        return danLi;
    }

方式二:双重检查锁定

public static DanLi getDanLi() {
        if (danLi == null) {
            synchronized (DanLi.class) {
                if (danLi == null) {
                    danLi = new DanLi();
                }
            }
        }
        return danLi;
    }

方式三:静态内部类

/**
 * 懒汉式单例类——线程安全
 * 在第一次调用的时候实例化自己
 */
public class DanLi {

    //构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象,
    // 只有通过该类提供的静态方法来得到该类的唯一实例
    private DanLi() {
    }

    //创建静态内部类
    private static class LazyHolder {
        private static final DanLi DAN_LI = new DanLi();
    }

    //创建静态对象
    private static DanLi danLi = null;

    //在该类内提供一个静态方法
    // 当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用。
    public static final DanLi getDanLi() {
        return LazyHolder.DAN_LI;
    }
}

饿汉式单例——线程安全

/**
 * 饿汉式单例类.在类初始化时,已经自行实例化
 * 饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的
 */
public class EHanDanLi {
    //创建私有的构造方法
    private EHanDanLi() {
    }

    //在类创建的同时就已经创建好一个静态的对象供系统使用
    private static final EHanDanLi E_HAN_DAN_LI = new EHanDanLi();

    //静态工厂方法
    public static EHanDanLi geteHanDanLi() {
        return E_HAN_DAN_LI;
    }
}

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

饿汉式和懒汉式区别

饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题;

懒汉式本身是非线程安全的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YD_1989

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值