饿汉式单例模式和懒汉式单例模式及其一些所涉及到的问题

class Singleton{  // Singleton.class
    // @2
    private static Singleton instance = new Singleton();

    // @3
    public static Singleton getInstance(){
        return instance;
    }

    // @1
    private Singleton(){
        System.out.println("call Singleton()");
    }
}*/

/**
 * 懒汉式单例模式  为什么要考虑它的线程安全问题???
 */
/*class Singleton{
    // @2
    private static Singleton instance = null;

    // @3
    public synchronized static Singleton getInstance(){
        if(instance == null){
            *//**
             * 1.给Singleton对象分配内存
             * 3.对象的地址赋给instance变量
             *         ==================>
             *
             * 2.调用Singleton构造函数构造对象
             *
             *//*
            instance = new Singleton();
        }
        return instance;
    }

    // @1
    private Singleton(){

    }
}*/

/**
 * 线程安全的懒汉式单例模式
 * 借助Java的内部类,快速实现一个线程安全的懒汉式单例模式
 */
class Singleton{

    // @2 定义一个静态内部类
    private static class InnerClass{
        // 静态成员变量的初始化jvm保证它们的线程安全
        static Singleton instance = new Singleton();
    }

    // @3
    public Singleton getInstance(){
        return InnerClass.instance;
    }

    // @1
    private Singleton(){
        System.out.println("call Singleton()");
    }
}

// 基类类型
class Man{
    private static Integer value1;

    static {
        System.out.println("Man static init");
        value1 = 20;
    }
}

class Teacher extends Man{
    private static Integer value2;

    static {
        System.out.println("Teacher static init");
        value2 = 20;
    }
}

/**
 * 描述: 单例模式的实现
 * 类的加载过程和类加载器
 * 类加载器:主要分为三种
 * Bootstrap ClassLoader:引导类加载器,主要负责加载jvm运行依赖的库,路径是jdk/jre/lib下的jar包
 * ExtClassLoader: 扩展类加载器,主要负载加载jdk/jre/lib/ext路径下的类库(jar包)
 * AppClassLoader: 应用类加载器,主要根据CLASS_PATH配置的路径,找相应的类的字节码文件*.class
 * 注意:Bootstrap ClassLoader的信息在jvm上是无法获取的
 *
 * 类的加载过程了(当我们第一次使用某个类的时候,才去加载相应的类型):
 * Student stu = new Student();
 * 1. 加载
 *    用类加载器,在指定的路径上,加载对应的class字节码文件 Teacher.class => 类型的Class对象
 *
 * 2. 链接  => 准备、验证、引用
 *    a.验证上面的字节码文件,是否能够在当前的jvm上运行;
 *    b.给static成员开辟内存
 *    c.它如果有基类,那么重复上面的步骤,加载基类
 *
 * 3. 初始化
 *    给static静态成员进行初始化工作
 *
 * @Author shilei
 * @Date 2019/4/27
 */
public class SingletonTest {
    public static void main(String[] args) throws Exception{

        Class c = Singleton.class;  // new Singleton();
        // getInstance方法???
        Class c2 = Class.forName("com.com.tulun2.Singleton");

        //Class c = Teacher.class;
        /**
         * 1.通过类加载器找Teacher.class字节码文件,并从字节码文件中加载类型的Class对象
         * 2.验证Class对象是否能够在当前jvm上运行    
         *   给Teacher的static成员开辟内存
         *   看Teacher有没有基类,有的话,重复上面的操作步骤
         * 3.给static成员进行初始化操作
         */
        //Teacher t = new Teacher();

        // Class c   <=   SingletonTest类类型的身份证信息
        // Class c = SingletonTest.class;

        // SingletonTest  =>  第一次使用这个类,才加载这个类
        /**
         * java   环境变量CLASS_PATH
         * .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar    . 表示工程路径
         * SingletonTest.class  => 类加载器  =>  加载类型的Class对象
         *
         * java HelloWorld
         * java => jvm => system
         *
         * C:\Program Files\Java\jdk1.8.0_192\jre\lib
         * Bootstrap ClassLoader 引导类加载器  C/C++语言实现的  原生代码实现的        引导类加载器加载生成jvm(java虚拟机加载器)
         *     |
         * C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext
         * ExtClassLoader 扩展类加载器
         *     |
         * ===》 从CLASS_PATH指定的路径里面加载需要的类型
         * AppClassLoader 应用类加载器  <=>  SystemClassLoader  系统类加载器
         *
         *
         */
        //SingletonTest s = new SingletonTest();
        //AppClassLoader
        //System.out.println(s.getClass().getClassLoader());
        //ExtClassLoader
        //System.out.println(s.getClass().getClassLoader().getParent());
        //null
        //System.out.println(s.getClass().getClassLoader().getParent().getParent());

        //String str = new String(""); // String.class
        // null
        //System.out.println(str.getClass().getClassLoader());

        /*Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        Singleton s3 = Singleton.getInstance();*/
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41241541/article/details/89881572