package com.sise.case1;//单例模式 1.私有的静态的实例对象 private static instance//// 2.私有的构造函数(保证在该类外部,无法通过new的方式来创建对象实例) private Singleton(){}//// 3.公有的、静态的、访问该实例对象的方法 public static Singleton getInstance(){}public class TestSingleton { public static void main(String[] args) { //懒汉/** LazySingleton instance1 = LazySingleton.getInstance(); System.out.println(instance1); LazySingleton instance2 = LazySingleton.getInstance(); System.out.println(instance2); System.out.println(instance1==instance2);**/ new Thread(){ @Override public void run() { LazySingleton instance3 = LazySingleton.getInstance(); System.out.println(instance3); } }.start(); new Thread(){ @Override public void run() { LazySingleton instance4 = LazySingleton.getInstance(); System.out.println(instance4); } }.start();//com.sise.case1.LazySingleton@55ca3d7b//com.sise.case1.LazySingleton@6d5f1f70 }}class LazySingleton{//懒汉模式 ;延迟加载,只要需要用到时才开始进行实例化 //问题:1.线程安全-》判断null // 2.通过反射创建实例 // 3.jit,cpu有可能对指令进行重排序,大只使用尚未初始化的实例可通过volatile关键字进行修饰,防止指令重排 // #1 //饿汉直接创建实例 private volatile static LazySingleton instance = new LazySingleton(); private volatile static LazySingleton instance;// 字节码层面:1.分配空间 2.初始化 3.引用赋值 (指令重排序 2和3顺序调换,报空指针错误,,需要加上volatile). //声明构造器,防止外部new方法外部进行实例化 //#2 private void LazySingleton(){} //全局访问点 //#3 public static LazySingleton getInstance(){ //#4 if (instance==null) {//两个线程可能同时进入 //线程等待同时进入 解决方法:1.给方法加上synchronized 2.给代码块加上锁 // 字节码层面:1.分配空间 2.初始化 3.引用赋值 (指令重排 2和3顺序调换,报空指针错误,,需要加上volatile)./** try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } instance = new LazySingleton(); **/ //进行加锁 synchronized (LazySingleton.class){ if(instance==null){//防止一个线程创建了实例 instance = new LazySingleton(); } } } return instance; }//类加载过程:1.加载二进制数据到内存,生成相对应class数据结构// 2.连接:a验证 b准备c解析// 3.初始化:给类的静态变量赋初值 //真正使用对应的类时才会触发初始化:(进行new操作,访问静态属性,访问静态方法,用反射访问类,初始化一个类的子类) //静态内部类方法实现单例模式:1.通过类加载机制保证线程安全 2.懒加载}
来源:https://www.cnblogs.com/oo-llm/p/12041787.html