单列设计模式 懒汉式及多线程debug

我们也是遵循演进的一个方式,一点点体会他们的不同,以及优缺点,单例模式也是创建型模式,我们在这个包下创建

一个包,我们先学习一下懒汉式单例模式
package com.learn.design.pattern.creational.singleton;

/**
 * 
 * @author Leon.Sun
 *
 */
public class LazySingleton {
	/**
	 * 首先我们声明一个静态的单例的一个对象
	 * 懒汉式可以理解说他比较懒
	 * 在初始化的时候呢
	 * 是没有创建的
	 * 而是做一个延迟加载
	 * 为了不让外部来进行new
	 * 这两个点都比较好理解
	 * 
	 * 
	 */
    private static LazySingleton lazySingleton = null;
    private LazySingleton(){
        if(lazySingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }
    
    /**
     * 我们写一个获取LazySingleton的一个方法
     * 他呢肯定是public的
     * getInstance
     * 这里面很简单
     * 
     * 第一种方式我们在getInstance方法上
     * 加上synchronized这个关键字
     * 是这个方法变成同步方法
     * 如果这个锁加载静态方法上
     * 相当于锁的是LazySingleton这个类的clas文件
     * 如果这个不是静态方法呢
     * 相当于锁是在堆内存中生成的对象
     * 这里要注意一下
     * 也就是说在静态方法中
     * 我们加了synchronized这个关键字
     * 来锁这个方法的时候
     * 相当于锁了这个类
     * 那我们换一种写法
     * 
     * 这个时候Thread0进入这个方法
     * 我们再切入到Thread1上
     * 可以看到断点并没有往下跳
     * 同时这个线程的状态变成Monitor
     * 那我们可以认为Thread1现在是阻塞状态
     * 这个是一个监视锁
     * 我们可以看到下边有一个提示
     * 这个提示很清晰
     * Thead1被线程0给阻塞了
     * 下面有一个蓝色的按钮
     * 如果点的话
     * 就会继续线程0
     * 所以Thread1进不了getInstance的方法
     * 我们再切回Thread0
     * 单步走返回了
     * 然后准备输出了
     * 我们再切回Thread1
     * 我们可以看到Thread1是Running状态
     * F6单步
     * 这个时候我们看一下
     * 因为在if(lazySingleton == null)的时候
     * Thread0已经new完了
     * LazySingleton并不等于空
     * 他们两返回的是同一个对象
     * 并且在LazySingleton里面
     * 这个时候只生产了一个实例
     * F8直接过
     * 看一下console
     * 这两个拿到的也是同一个对象
     * 通过这种同步的方式
     * 我们解决了懒汉式在多线程可能引起的问题
     * 那我们也知道synchronized比较消耗资源
     * 这里面有一个加锁和解锁的一个开销
     * 而且synchronized修饰static方法的时候
     * 锁的是这个class
     * 这个锁的范围也是非常大的
     * 对性能也会有一定的影响
     * 那我们还有没有一种方式继续演进
     * 在性能和安全性方面取得平衡
     * 答案是有的
     * 那我们现在继续演进我们的懒汉式
     * 
     * 
     * 
     * @return
     */
    public synchronized static LazySingleton getInstance(){
//    public static LazySingleton getInstance(){
    	/**
    	 * 刚刚写静态锁的这种写法和现在这种写法是一样的
    	 * synchronized (LazySingleton.class)这里锁的也是LazySingleton
    	 * 那么再复原成同步方法
    	 * public synchronized static LazySingleton getInstance()
    	 * 就是这个样子的
    	 * 
    	 * 
    	 */
//    	synchronized (LazySingleton.class) {
        	/**
        	 * 做一个空判断
        	 * 如果lazySingleton为null的话
        	 * 给他赋值
        	 * new一个LazySingleton
        	 * 
        	 * 最开始的时候lazySingleton为null
        	 * 因为判断lazySingleton == null结果为true
        	 * 进入到lazySingleton = new LazySingleton();
        	 * 进入之后还没有执行new
        	 * 这个时候执行lazySingleton = new LazySingleton();
        	 * 这个单例就有值了
        	 * 
        	 * 我们单步来到if(lazySingleton == null)
        	 * debug来调试多线程的节奏
        	 * 来触发这种写法在多线程中的问题
        	 * 那之前run的时候没有发生这种问题呢
        	 * 那我们看到的是表象没有发生
        	 * 但是实际有没有发生其实是不确定的
        	 * 另外一种就是实际就没有发生
        	 * 但是对于发生了但是我们没有看到
        	 * 这种情况只要我们接着往下看
        	 * 肯定就理解了
        	 * 那另外一个他没有发生
        	 * 这个呢也很好理解
        	 * 他就是没有发生
        	 * 我说的发生是多线程的问题
        	 * 也就是这个单例模式是否只new出来一个对象
        	 * 那如果我们没有用断点干预
        	 * 直接run的话
        	 * 和CPU分配的时间有关
        	 * 是有一定概率的
        	 * 我们现在程序比较简单
        	 * 如果我们程序复杂一些
        	 * 这种隐患还是有可能发生的
        	 * 既然有隐患我们就要消除掉他
        	 * 那现在我们继续来看一下他
        	 * 把这个隐患找出来
        	 * 一定要掌握多线程debug
        	 * 讲TOMCAT集群的时候呢
        	 * 操作了都进程debug
        	 * 现在在设计模式的课程中
        	 * 我们在写多线程debug
        	 * 这个技能非常重要
        	 * 一定要学会
        	 * 
        	 * 因为Thread0并没有赋值上
        	 * 所以他还是为空
        	 * F6单步
        	 * 他也进来了
        	 * 那我再切回Thread0
        	 * 
        	 * 我们切换到Thread0线程上
        	 * 为null进来
        	 * 
        	 * 单步Thread1也进来了
        	 * 现在对于Thread1我直接让他返回
        	 * 已经输出了
        	 * 那我们再切回Thread0上
        	 * 这个时候Thread1是431
        	 * 但是lazySingleton = new LazySingleton()一旦完成
        	 * 那这个对象就变了
        	 * 已经变成了432
        	 * 这个时候他就返回
        	 * 然后输出
        	 * 我们再看一下console
        	 * 那这个时候我们就可以看到
        	 * Thread1拿到的42D这个对象
        	 * Thread0是拿到420这个对象
        	 * 所以呢我们不能被表面所迷惑
        	 * 例如我们直接run的时候
        	 * 看到的对象是同一个
        	 * 但是在这中间获取的可能不止一个对象
        	 * 所以呢这个是有一定概率的
        	 * 例如在lazySingleton里面
        	 * 如果第一个线程执行特别快
        	 * 先new上了
        	 * 那第二个线程判断为null的时候
        	 * 就会返回false
        	 * 然后直接return
        	 * 所以呢
        	 * 具体这个返回值什么样子
        	 * 都是有一定概率的
        	 * 那这个隐患我们是一定要消除的
        	 * 怎么消除呢
        	 * 很简单
        	 * 对于懒汉式这种方式呢
        	 * 首先我们来到lazySingleton里边
        	 * 
        	 * 
        	 */
            if(lazySingleton == null){
            	/**
            	 * 第一个线程到这里的时候并且没有执行这一行
            	 * 第二个线程达到if(lazySingleton == null)这里
            	 * 那if(lazySingleton == null)这一行判断
            	 * 因为lazySingleton = new LazySingleton();这里还没有new
            	 * 那么if(lazySingleton == null)判断的结果是true
            	 * 所以第二个线程也会进入到lazySingleton = new LazySingleton();
            	 * 那这个对象就new了两次
            	 * 同时会返回最后执行的lazySingleton
            	 * 那我们怎么验证呢
            	 * 我们写一个测试类
            	 * 
            	 * 懒汉式注重的是延迟加载
            	 * 
            	 * 这个时候lazySingleton还是null
            	 * 因为lazySingleton赋值new LazySingleton()
            	 * 这一行还没有执行完
            	 * 所以他并没有被复制上
            	 * 这个时候我们切到Thread1上
            	 * Thread1单步
            	 * 
            	 * 可以看到在lazySingleton = new LazySingleton()还没有执行的时候
            	 * lazySingleton是有值的
            	 * 但是我们马上就要执行它了
            	 * F6单步
            	 * 现在可以看到lazySingleton值变了
            	 * 也就是说在我们写的懒汉式的单例模式中
            	 * lazySingleton在多线程的模式中
            	 * 生成了不止一个实例
            	 * 那现在是两个线程
            	 * 如果是多个线程呢
            	 * 所以在第一次初始化的时候
            	 * 有可能创建很多个的单例对象
            	 * 如果这个单例类的对象特别消耗资源
            	 * 那很有可能造成系统故障
            	 * 这个呢是非常有风险的
            	 * 那在我们这个例子中lazySingleton并没有特别消耗资源的地方
            	 * 但是场景是一样的
            	 * 那我们现在再切换到Thread0上
            	 * lazySingleton这个对象已经被Thread1重新赋值了
            	 * 那现在F8过
            	 * 主动跳到主线程
            	 * 我们看一下console
            	 * 这个时候我们可以看到
            	 * Thread0和Thread1拿到的还是同一个对象
            	 * 
            	 * 现在Thread0在lazySingleton = new LazySingleton();这一行上
            	 * 我们再切换到Thread1上
            	 * 
            	 * 
            	 */
                lazySingleton = new LazySingleton();
            }
//		}
    	/**
    	 * 把这个对象返回
    	 * 把这个对象返回回去
    	 * 这种方式是线程不安全的
    	 * 我们看一看代码
    	 * 在单线程的时候
    	 * 这种模式这种写法
    	 * 是OK的
    	 * 但是一旦多线程来使用这个单例的话
    	 * 假设我们现在两个线程
    	 * 
    	 * 这个时候Thread0已经把lazySingleton赋值上了
    	 * 这个时候我们在切到Thread1上
    	 * 
    	 * 
    	 */
    	return lazySingleton;
    }

//    public static void main(String[] args) throws Exception {
//        Class objectClass = LazySingleton.class;
//        Constructor c = objectClass.getDeclaredConstructor();
//        c.setAccessible(true);
//
    	  /**
    	   * 通过LazySingleton这个类调用getInstance方法
    	   * 因为它是private构造器
    	   * 所以在外部是new不到他的
    	   * 然后我们直接getInstance
    	   * 
    	   * 这样简单一个单线程获取的单例呢就完成了
    	   * 只有使用它的时候才初始化
    	   * 如果不使用就初始化LazySingleton对象
    	   * 那main本身是一个线程
    	   * 现在我们在这个线程中再创建两个线程
    	   * 去获取现在这种写法的单例的时候
    	   * 会碰到什么问题呢
    	   * 我们一起来看一下
    	   * 首先我们写一下线程的类
    	   * 
    	   * 
    	   * 
    	   */
//        LazySingleton o1 = LazySingleton.getInstance();
//        System.out.println("Program end.....");
//
//        Field flag = o1.getClass().getDeclaredField("flag");
//        flag.setAccessible(true);
//        flag.set(o1,true);
//
//
//        LazySingleton o2 = (LazySingleton) c.newInstance();
//
//        System.out.println(o1);
//        System.out.println(o2);
//        System.out.println(o1==o2);
//    }

}
package com.learn.design.pattern.creational.singleton;

/**
 * 
 * @author Leon.Sun
 *
 */
public class LazySingleton {
	/**
	 * 首先我们声明一个静态的单例的一个对象
	 * 懒汉式可以理解说他比较懒
	 * 在初始化的时候呢
	 * 是没有创建的
	 * 而是做一个延迟加载
	 * 为了不让外部来进行new
	 * 这两个点都比较好理解
	 * 
	 * 
	 */
    private static LazySingleton lazySingleton = null;
    private LazySingleton(){
        if(lazySingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }
    
    /**
     * 我们写一个获取LazySingleton的一个方法
     * 他呢肯定是public的
     * getInstance
     * 这里面很简单
     * 
     * 第一种方式我们在getInstance方法上
     * 加上synchronized这个关键字
     * 是这个方法变成同步方法
     * 如果这个锁加载静态方法上
     * 相当于锁的是LazySingleton这个类的clas文件
     * 如果这个不是静态方法呢
     * 相当于锁是在堆内存中生成的对象
     * 这里要注意一下
     * 也就是说在静态方法中
     * 我们加了synchronized这个关键字
     * 来锁这个方法的时候
     * 相当于锁了这个类
     * 那我们换一种写法
     * 
     * 这个时候Thread0进入这个方法
     * 我们再切入到Thread1上
     * 可以看到断点并没有往下跳
     * 同时这个线程的状态变成Monitor
     * 那我们可以认为Thread1现在是阻塞状态
     * 这个是一个监视锁
     * 我们可以看到下边有一个提示
     * 这个提示很清晰
     * Thead1被线程0给阻塞了
     * 下面有一个蓝色的按钮
     * 如果点的话
     * 就会继续线程0
     * 所以Thread1进不了getInstance的方法
     * 我们再切回Thread0
     * 单步走返回了
     * 然后准备输出了
     * 我们再切回Thread1
     * 我们可以看到Thread1是Running状态
     * F6单步
     * 这个时候我们看一下
     * 因为在if(lazySingleton == null)的时候
     * Thread0已经new完了
     * LazySingleton并不等于空
     * 他们两返回的是同一个对象
     * 并且在LazySingleton里面
     * 这个时候只生产了一个实例
     * F8直接过
     * 看一下console
     * 这两个拿到的也是同一个对象
     * 通过这种同步的方式
     * 我们解决了懒汉式在多线程可能引起的问题
     * 那我们也知道synchronized比较消耗资源
     * 这里面有一个加锁和解锁的一个开销
     * 而且synchronized修饰static方法的时候
     * 锁的是这个class
     * 这个锁的范围也是非常大的
     * 对性能也会有一定的影响
     * 那我们还有没有一种方式继续演进
     * 在性能和安全性方面取得平衡
     * 答案是有的
     * 那我们现在继续演进我们的懒汉式
     * 
     * 
     * 
     * @return
     */
    public synchronized static LazySingleton getInstance(){
//    public static LazySingleton getInstance(){
    	/**
    	 * 刚刚写静态锁的这种写法和现在这种写法是一样的
    	 * synchronized (LazySingleton.class)这里锁的也是LazySingleton
    	 * 那么再复原成同步方法
    	 * public synchronized static LazySingleton getInstance()
    	 * 就是这个样子的
    	 * 
    	 * 
    	 */
//    	synchronized (LazySingleton.class) {
        	/**
        	 * 做一个空判断
        	 * 如果lazySingleton为null的话
        	 * 给他赋值
        	 * new一个LazySingleton
        	 * 
        	 * 最开始的时候lazySingleton为null
        	 * 因为判断lazySingleton == null结果为true
        	 * 进入到lazySingleton = new LazySingleton();
        	 * 进入之后还没有执行new
        	 * 这个时候执行lazySingleton = new LazySingleton();
        	 * 这个单例就有值了
        	 * 
        	 * 我们单步来到if(lazySingleton == null)
        	 * debug来调试多线程的节奏
        	 * 来触发这种写法在多线程中的问题
        	 * 那之前run的时候没有发生这种问题呢
        	 * 那我们看到的是表象没有发生
        	 * 但是实际有没有发生其实是不确定的
        	 * 另外一种就是实际就没有发生
        	 * 但是对于发生了但是我们没有看到
        	 * 这种情况只要我们接着往下看
        	 * 肯定就理解了
        	 * 那另外一个他没有发生
        	 * 这个呢也很好理解
        	 * 他就是没有发生
        	 * 我说的发生是多线程的问题
        	 * 也就是这个单例模式是否只new出来一个对象
        	 * 那如果我们没有用断点干预
        	 * 直接run的话
        	 * 和CPU分配的时间有关
        	 * 是有一定概率的
        	 * 我们现在程序比较简单
        	 * 如果我们程序复杂一些
        	 * 这种隐患还是有可能发生的
        	 * 既然有隐患我们就要消除掉他
        	 * 那现在我们继续来看一下他
        	 * 把这个隐患找出来
        	 * 一定要掌握多线程debug
        	 * 讲TOMCAT集群的时候呢
        	 * 操作了都进程debug
        	 * 现在在设计模式的课程中
        	 * 我们在写多线程debug
        	 * 这个技能非常重要
        	 * 一定要学会
        	 * 
        	 * 因为Thread0并没有赋值上
        	 * 所以他还是为空
        	 * F6单步
        	 * 他也进来了
        	 * 那我再切回Thread0
        	 * 
        	 * 我们切换到Thread0线程上
        	 * 为null进来
        	 * 
        	 * 单步Thread1也进来了
        	 * 现在对于Thread1我直接让他返回
        	 * 已经输出了
        	 * 那我们再切回Thread0上
        	 * 这个时候Thread1是431
        	 * 但是lazySingleton = new LazySingleton()一旦完成
        	 * 那这个对象就变了
        	 * 已经变成了432
        	 * 这个时候他就返回
        	 * 然后输出
        	 * 我们再看一下console
        	 * 那这个时候我们就可以看到
        	 * Thread1拿到的42D这个对象
        	 * Thread0是拿到420这个对象
        	 * 所以呢我们不能被表面所迷惑
        	 * 例如我们直接run的时候
        	 * 看到的对象是同一个
        	 * 但是在这中间获取的可能不止一个对象
        	 * 所以呢这个是有一定概率的
        	 * 例如在lazySingleton里面
        	 * 如果第一个线程执行特别快
        	 * 先new上了
        	 * 那第二个线程判断为null的时候
        	 * 就会返回false
        	 * 然后直接return
        	 * 所以呢
        	 * 具体这个返回值什么样子
        	 * 都是有一定概率的
        	 * 那这个隐患我们是一定要消除的
        	 * 怎么消除呢
        	 * 很简单
        	 * 对于懒汉式这种方式呢
        	 * 首先我们来到lazySingleton里边
        	 * 
        	 * 
        	 */
            if(lazySingleton == null){
            	/**
            	 * 第一个线程到这里的时候并且没有执行这一行
            	 * 第二个线程达到if(lazySingleton == null)这里
            	 * 那if(lazySingleton == null)这一行判断
            	 * 因为lazySingleton = new LazySingleton();这里还没有new
            	 * 那么if(lazySingleton == null)判断的结果是true
            	 * 所以第二个线程也会进入到lazySingleton = new LazySingleton();
            	 * 那这个对象就new了两次
            	 * 同时会返回最后执行的lazySingleton
            	 * 那我们怎么验证呢
            	 * 我们写一个测试类
            	 * 
            	 * 懒汉式注重的是延迟加载
            	 * 
            	 * 这个时候lazySingleton还是null
            	 * 因为lazySingleton赋值new LazySingleton()
            	 * 这一行还没有执行完
            	 * 所以他并没有被复制上
            	 * 这个时候我们切到Thread1上
            	 * Thread1单步
            	 * 
            	 * 可以看到在lazySingleton = new LazySingleton()还没有执行的时候
            	 * lazySingleton是有值的
            	 * 但是我们马上就要执行它了
            	 * F6单步
            	 * 现在可以看到lazySingleton值变了
            	 * 也就是说在我们写的懒汉式的单例模式中
            	 * lazySingleton在多线程的模式中
            	 * 生成了不止一个实例
            	 * 那现在是两个线程
            	 * 如果是多个线程呢
            	 * 所以在第一次初始化的时候
            	 * 有可能创建很多个的单例对象
            	 * 如果这个单例类的对象特别消耗资源
            	 * 那很有可能造成系统故障
            	 * 这个呢是非常有风险的
            	 * 那在我们这个例子中lazySingleton并没有特别消耗资源的地方
            	 * 但是场景是一样的
            	 * 那我们现在再切换到Thread0上
            	 * lazySingleton这个对象已经被Thread1重新赋值了
            	 * 那现在F8过
            	 * 主动跳到主线程
            	 * 我们看一下console
            	 * 这个时候我们可以看到
            	 * Thread0和Thread1拿到的还是同一个对象
            	 * 
            	 * 现在Thread0在lazySingleton = new LazySingleton();这一行上
            	 * 我们再切换到Thread1上
            	 * 
            	 * 
            	 */
                lazySingleton = new LazySingleton();
            }
//		}
    	/**
    	 * 把这个对象返回
    	 * 把这个对象返回回去
    	 * 这种方式是线程不安全的
    	 * 我们看一看代码
    	 * 在单线程的时候
    	 * 这种模式这种写法
    	 * 是OK的
    	 * 但是一旦多线程来使用这个单例的话
    	 * 假设我们现在两个线程
    	 * 
    	 * 这个时候Thread0已经把lazySingleton赋值上了
    	 * 这个时候我们在切到Thread1上
    	 * 
    	 * 
    	 */
    	return lazySingleton;
    }

//    public static void main(String[] args) throws Exception {
//        Class objectClass = LazySingleton.class;
//        Constructor c = objectClass.getDeclaredConstructor();
//        c.setAccessible(true);
//
    	  /**
    	   * 通过LazySingleton这个类调用getInstance方法
    	   * 因为它是private构造器
    	   * 所以在外部是new不到他的
    	   * 然后我们直接getInstance
    	   * 
    	   * 这样简单一个单线程获取的单例呢就完成了
    	   * 只有使用它的时候才初始化
    	   * 如果不使用就初始化LazySingleton对象
    	   * 那main本身是一个线程
    	   * 现在我们在这个线程中再创建两个线程
    	   * 去获取现在这种写法的单例的时候
    	   * 会碰到什么问题呢
    	   * 我们一起来看一下
    	   * 首先我们写一下线程的类
    	   * 
    	   * 
    	   * 
    	   */
//        LazySingleton o1 = LazySingleton.getInstance();
//        System.out.println("Program end.....");
//
//        Field flag = o1.getClass().getDeclaredField("flag");
//        flag.setAccessible(true);
//        flag.set(o1,true);
//
//
//        LazySingleton o2 = (LazySingleton) c.newInstance();
//
//        System.out.println(o1);
//        System.out.println(o2);
//        System.out.println(o1==o2);
//    }

}
package com.learn.design.pattern.creational.singleton;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

/**
 * 本身Main是一个主线程
 * 从上至下而执行
 * 那执行到t1.start();的时候呢
 * 就开启了两个线程
 * 一会我们在执行的时候其实是三个线程在执行
 * 主线程还有t1和t2
 * 那断点呢我们也打上了
 * 现在运行debug
 * 
 * 但是刚刚通过debug我们已经知道了
 * 他们返回同一个对象
 * 是因为最后的线程重新赋值了
 * 并且在重新赋值之后
 * 两个线程才进行return的
 * 所以我们在console里面看到的是同一个对象
 * 把我们再debug操作一下
 * 让他们返回不同的对象
 * 
 * 
 * @author Leon.Sun
 *
 */
public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();

//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());
//        System.out.println("main thread"+ThreadLocalInstance.getInstance());

        /**
         * new一个t1线程
         * 
         */
        Thread t1 = new Thread(new T());
        /**
         * 再new一个t2线程
         * 
         */
        Thread t2 = new Thread(new T());
        /**
         * 我们可以看到Thread1和Thread0拿到的是同一个对象
         * 那这个呢是run的情况下
         * 如果我们debug进行干预的话
         * 
         * 
         */
        t1.start();
        t2.start();
        /**
         * 现在这个线程是主线程的
         * 我们关心的是Main Thread0 Thread1
         * 那现在这个三个线程的状态都是Running
         * 那我们现在通过Frame切换到Thread0上
         * 可以看到Thread0调用getInstance方法了
         * 
         * 
         */
        System.out.println("program end");

//        HungrySingleton instance = HungrySingleton.getInstance();
//        EnumInstance instance = EnumInstance.getInstance();
//        instance.setData(new Object());
//
//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
//        oos.writeObject(instance);
//
//        File file = new File("singleton_file");
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
//
        HungrySingleton newInstance = (HungrySingleton) ois.readObject();
//        EnumInstance newInstance = (EnumInstance) ois.readObject();
//
//        System.out.println(instance.getData());
//        System.out.println(newInstance.getData());
//        System.out.println(instance.getData() == newInstance.getData());

//        Class objectClass = HungrySingleton.class;
//        Class objectClass = StaticInnerClassSingleton.class;

//        Class objectClass = LazySingleton.class;
//        Class objectClass = EnumInstance.class;

//        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
//
//        constructor.setAccessible(true);
//        EnumInstance instance = (EnumInstance) constructor.newInstance("Geely",666);


//
//        LazySingleton newInstance = (LazySingleton) constructor.newInstance();
//        LazySingleton instance = LazySingleton.getInstance();



//        StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
//        StaticInnerClassSingleton newInstance = (StaticInnerClassSingleton) constructor.newInstance();

//        HungrySingleton newInstance = (HungrySingleton) constructor.newInstance();
//        HungrySingleton instance = HungrySingleton.getInstance();


//        System.out.println(instance);
//        System.out.println(newInstance);
//        System.out.println(instance == newInstance);

//        EnumInstance instance = EnumInstance.getInstance();
//        instance.printTest();


    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值