创建单例模式

懒汉式 和 饿汉时

public class Singleton {
    /**
     * 懒汉式:在真正 需要使用对象时 才去创建该单例类对象
     *  在程序使用对象前,先判断该对象是否已经实例化(判空),若已实例化直接返回该类对象,否则则先执行实例化操作。
     */
    //1.0
    //两个线程同时判断singleton为空,那么它们都会去实例化一个Singleton对象,这就变成双例了
//    private static Singleton singleton;
//    private Singleton(){}
//    public static Singleton getInstance() {
//        if (singleton == null) {
//            singleton = new Singleton();
//        }
//        return singleton;
//    }
    //2.0 解决线程安全问题
    //每次去获取对象都需要先获取锁,并发性能非常地差,极端情况下,可能会出现卡顿现象。
//    private static Singleton singleton;
//    private Singleton(){}
//    public static synchronized Singleton getInstance() {
//        if (singleton == null) {
//            singleton = new Singleton();
//        }
//        return singleton;
//    }
//    private static Singleton singleton;
//    private Singleton(){}
//    public static Singleton getInstance() {
//        synchronized (Singleton.class) {
//            if (singleton == null) {
//                singleton = new Singleton();
//            }
//        }
//        return singleton;
//    }
    //3.0 解决卡顿现象 Double Check(双重校验) + Lock(加锁)
    //优化性能:如果没有实例化对象则加锁创建,如果已经实例化了,则不需要加锁,直接获取实例,所以直接在方法上加锁的方式就被废掉了,因为这种方式无论如何都需要先获取
    //存在最后一个问题:指令重排
//    private static Singleton singleton;
//    private Singleton(){}
//    public static Singleton getInstance() {
//        if (singleton == null) { //如果singleton不为空,则直接返回对象,不需要获取锁;而如果多个线程发现singleton为空,则进入分支;
//            synchronized (Singleton.class) { //多个线程尝试争抢同一个锁,只有一个线程争抢成功,第一个获取到锁的线程会再次判断singleton是否为空,因为singleton有可能已经被之前的线程实例化
//                if (singleton == null) { //发现singleton已经不为空了,则不会再new一个对象,直接返回对象即可
//                    singleton = new Singleton();
//                }
//            }
//        }
//        return singleton;
//    }
    //4.0 解决指令重排:使用volatile关键字修饰的变量
    //指令重排序是指:JVM在保证最终结果正确的情况下,可以不按照程序编码的顺序执行语句,尽可能提高程序的性能
    // 有序性:可以保证其指令执行的顺序与程序指明的顺序一致,不会发生顺序变换
    // 内存可见性:每一时刻线程读取到该变量的值都是内存中最新的那个值,线程每次操作该变量都需要先读取该变量。
//    private static volatile Singleton singleton;
//    private Singleton(){}
//    public static Singleton getInstance() {
//        if (singleton == null) { //如果singleton不为空,则直接返回对象,不需要获取锁;而如果多个线程发现singleton为空,则进入分支;
//            synchronized (Singleton.class) { //多个线程尝试争抢同一个锁,只有一个线程争抢成功,第一个获取到锁的线程会再次判断singleton是否为空,因为singleton有可能已经被之前的线程实例化
//                if (singleton == null) { //发现singleton已经不为空了,则不会再new一个对象,直接返回对象即可
//                    singleton = new Singleton();
//                }
//            }
//        }
//        return singleton;
//    }


    /**
     * 饿汉式:在类加载时已经创建好该单例对象,等待被程序使用
     *  在程序调用时直接返回该单例对象即可,即我们在编码时就已经指明了要马上创建这个对象,不需要等到被调用时再去创建。
     */
//    private static final Singleton singleton = new Singleton();
//    private Singleton() {}
//    public static Singleton getInstance() {
//        return singleton;
//    }
    
}

枚举

/**
 * 枚举实现单例的过程:在程序启动时,会调用Singleton的空参构造器,实例化好一个Singleton对象赋给INSTANCE,之后再也不会实例化
 *  优势1:代码对比饿汉式与懒汉式来说,更加地简洁
 *  优势2:它不需要做任何额外的操作去保证对象单一性与线程安全性
 *  优势3:使用枚举可以防止调用者使用反射、序列化与反序列化机制强制生成多个单例对象,破坏单例模式。
 */
public enum Singleton2 {
    INSTANCE;
    Singleton2() {} //枚举创建对象了
}
    //测试
//public enum Singleton2 {
//    INSTANCE;
//    Singleton2() {}
//    //测试方法
//    public static void test() {
//        Singleton2 t1 = Singleton2.INSTANCE;
//        Singleton2 t2 = Singleton2.INSTANCE;
//        System.out.println(t1 == t2); //true
//    }
//    public static void main(String[] args) {
//        test();
//    }
//}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值