核心 :
构造方法私有化全局静态对象一个类只能创建一个对象java中的单例写法
class VideoPlay { //普通单例模式 懒汉 private static VideoPlay ins = new VideoPlay(); private VideoPlay() { } public synchronized static VideoPlay getIns() { return VideoPlay.ins; } }饿汉式 双重锁(参考博客https://www.jianshu.com/p/b0e527336a72)
(JDK1.5后)使用volatile关键字修饰静态变量insvolatile可以避免指令重排,每一条线程取变量值都是从主储存里取,保证了变量是最新修改的指令重排导致的问题 Test c = new Test()理论过程为,1.分配内存 2.初始化 3.返回内存地址 Test c = new Test()实际过程为,1.分配内存 2.返回地址 3. 初始化当线程 A 执行 1.分配内存 2.返回地址 (还未初始化) 线程 B 发现ins不为空(还未初始化), 就直接拿来用 ,所以造成了不安全 class VideoPlay2 { //双重锁 JDK1.5写法 /** 使用 volatile 关键字 每次都从主储存取值(每次都能取到最新的值) 如果不加 volatile 关键字 jvm会对其进行指令重排 new VideoPlay2() 过程为 理论过程 :1.分配内存 2.初始化 3.返回内存地址 实际底层回进行重排过程 :1.分配内存 2.返回地址 3. 初始化 由于重排, 线程 A 执行1.分配内存 2.返回地址(还未初始化) 线程 B 发现ins不为空(还未初始化), 就直接拿来用 ,所以造成了不安全 */ private volatile static VideoPlay2 ins; public static VideoPlay2 getIns() { if(ins == null) { synchronized (VideoPlay2.class) { if(ins == null) ins = new VideoPlay2(); } } return ins; } }或则使用静态内部类实现 饿汉式 双重锁
class VideoPlay3 { //双重锁 使用静态内部类实现 private static class Helper { private static VideoPlay3 ins = new VideoPlay3(); } private VideoPlay3() { } public static final VideoPlay3 getIns() { return Helper.ins; } }