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.懒加载
}