Java设计模式之单例模式

学习内容:

1、 单例模式

  1. 饿汉式
// 单例模式的,饿汉式方式,这种单例模式是可以使用的,但缺点就是可能造成内存的浪费
// 因为有可能创建了这个类,但是在整个项目的运行过程中可能并没有使用到创建的当前对象
class SingleH{
    // 1.要实现单例模式,需要设置构造器私有化,禁止外部使用new创建实例对象
    private SingleH(){
    }
    
    // 2.使用静态方式创建本类内部的对象
    private static final SingleH instance = new SingleH();
    
    // 3.提供一个公有的静态方法,返回实例对象
    public static SingleH getInstance(){
        return instance;
    }
}
  1. 饿汉式(静态实现)
//使用静态代码块的方式实现对象的创建
class SingleHungryS {

    // 1.私有化构造方法
    private SingleHungryS() {
    }
    // 2.创建静态变量
    private static SingleHungryS instance;

    // 使用静态代码块实现对象的创建
    static {
        instance = new SingleHungryS();
    }
    
    // 3.提供一个公有的静态方法,返回实例对象
    public static SingleHungryS getInstance() {
        return instance;
    }
}
  1. 懒汉式(线程不安全)
// 单例模式:懒汉式(线程不安全),单线程下可以使用,多线程的情况下会出现线程不安全,所以在项目中不推荐使用
class SingleL{
    // 1.私有化构造方法
    private SingleL(){
    }
    
    // 2. 创建变量
    private static SingleL instance;

    // 3.给当前的静态变量进行赋值并进行返回
    public static SingleL getInstance(){
        // 先进行判断当前的对象是否存在,如果不存在则进行创建然后再返回对象,否则直接返回
        // 在这一步的时候可能会出现线程不安全的情况,假设当前有a,b两个线程都进入这个方法里面,
        // 此时a判断没有实例,就会进行创建,与此同时,在创建的时候,b也拿到了,发现也没有实例
        // 也会进行创建,那么此时就可能出现线程不安全的问题。
        if (instance == null){
            instance = new SingleL();
        }
        return instance;
    }
}
  1. 懒汉式(线程安全,但是效率太低)
// 单例模式:懒汉式(线程安全),单线程下可以使用,多线程的情况下会出现线程安全,
// 但是效率太低,所以在项目中不推荐使用
class SingleL2 {
    // 1.私有化构造方法
    private SingleL2() {
    }

    // 2. 创建变量
    private static SingleL2 instance;

    // 3.给当前的静态变量进行赋值并进行返回
    // 加入了同步synchronized实现了线程的同步安全问题,但是效率太低,不推荐使用
    // 因为在多线程的情况下,加入a线程拿到了,此时其他的线程就必须在外进行等候a线程
    // 执行完毕,才可以执行下一个线程,个人理解就好像是使用队列的操作(个人理解,大佬勿喷),
    public static synchronized SingleL2 getInstance() {
        // 先进行判断当前的对象是否存在,如果不存在则进行创建然后再返回对象,否则直接返回
        if (instance == null) {
            instance = new SingleL2();
        }
        return instance;
    }
}
  1. 懒汉式(双重检查,实际中推荐使用)
// 单例模式的懒加载方式,实现双重检查,并加入了同步机制,保证线程安全,并解决了饿汉式的内存浪费问题,
// 同时又保证了代码的效率问题,项目中推荐使用的方式
class SingleLP {
    // 1.私有化构造函数
    private SingleLP() {
    }

    // 2。设置同步变量,此时加入了volatile关键字
    private static volatile SingleLP instance;

    // 3.对象的构建并返回,使用synchronized实现线程安全的问题,假设来了多个线程,a拿到了线程,
    // 加入此时实例为空,那么其他的线程需要在函数外进行等待,a线程将会执行实例的创建工作,a线程
    // 执行完毕,其他的线程看到实例不为空就会直接进行返回当前的实例
    public static synchronized SingleLP getInstance() {
        if (instance == null) {
            // synchronized的参数表示对谁进行同步
            synchronized (SingleLP.class) {
                if (instance == null) {
                    instance = new SingleLP();
                }
            }
        }
        return instance;
    }
}
  1. 静态内部类的方式(推荐使用)
// 单例模式:使用静态类的方式
// 优点:避免了线程不安全的问题,利用静态内部类的特点实现了延迟加载,效率比较高,推荐使用
class SingleLazyPlusS {
    // 1.私有化构造函数
    private SingleLazyPlusS() {
    }

    // 2.创建静态内部类(不会随着类的加载而加载),只用执行getInstance()方法的时候才会执行静态内部类的创建
    private static class SingleTon {
        private static final SingleLazyPlusS INSTANCE = new SingleLazyPlusS();
    }

    // 3.执行调用实例的方法
    public static synchronized SingleLazyPlusS getInstance() {
        return SingleTon.INSTANCE;
    }
}
  1. 枚举实现单例模式
public class SingleEnum {
    public static void main(String[] args) {
        SingleE instance = SingleE.INSTANCE;
        SingleE instance1 = SingleE.INSTANCE;

        System.out.println("instance.hashCode() = " + instance.hashCode());
        System.out.println("instance1.hashCode() = " + instance1.hashCode());
        instance.sayOk();
    }
}

/**
 * 使用的枚举的方式实现单例模式
 * 枚举的方式不仅能够避免多线程同步的问题,还可以防止反序列化重新创建新的对象
  */
enum  SingleE{
    INSTANCE;

    public void sayOk(){
        System.out.println("ok");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值