目录
单例模式,属于创建类型的一种常用的软件设计模式。(23种设计模式之一)通过单例模式的方法创建的类在当前进程中只有一个实例
构造器私有化
定义静态变量存储这个对象唯一实例
直接暴露或者封装使用getter方法提供实例的获取
饿汉式、枚举饿汉式、懒汉式、双锁懒汉式、内部类懒汉式 五种
饿汉式:即当类初始化的时候就创建实例对象 --就叫做饿汉式
代码
- package com.sofwin.singletonDemo;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-饿汉式
- *
- * 要点:
- * 1.构造器私有化
- * 2.定义静态常量存储对象唯一实例
- * 3.通过getter方法获取实例对象
- */
- public class Singleton01 {
-
- /**
- * 构造器私有化
- */
- private static final Singleton01 SINGLETON_01 = new Singleton01();
-
-
- private Singleton01() {
- System.out.println("private Singleton01");
- }
-
- public static Singleton01 getSingleton01() {
- return SINGLETON_01;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
- }
测试
- package com.sofwin.singletonDemo;
-
- import org.junit.Test;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:09
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式的测试
- */
- public class SingletonTest {
-
- //单例模式-饿汉式
- @Test
- public void SinletonTest01() {
- //先判断是否类初始化的时候就创建对象了
- Singleton01.otherMethod();
- System.out.println("=================");
- Singleton01 singleton01 = Singleton01.getSingleton01();
- Singleton01 singleton02 = Singleton01.getSingleton01();
- System.out.println(singleton01);
- System.out.println(singleton02);
- }
- }
(类加载就创建实例---饿汉式)
这种设计有三种方法可以进行破坏
1、反射破坏单例
- package com.sofwin.singletonDemo;
-
- import org.junit.Test;
-
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:09
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式的测试
- */
- public class SingletonTest {
-
- //单例模式-饿汉式
- @Test
- public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
- //先判断是否类初始化的时候就创建对象了
- Singleton01.otherMethod();
- System.out.println("=================");
- Singleton01 singleton01 = Singleton01.getSingleton01();
- Singleton01 singleton02 = Singleton01.getSingleton01();
- System.out.println(singleton01);
- System.out.println(singleton02);
- System.out.println("暴力破解");
- SingletonTest.reflection(Singleton01.class);
- }
-
- /**
- * 反射破坏单例pos
- * @param clazz 类对象
- */
- public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor();
- //暴力破解
- declaredConstructor.setAccessible(true);
- //通过反射创建实例对象
- Object o = declaredConstructor.newInstance();
- System.out.println(o);
- }
- }
通过反射暴力破解,得到新的实例对象
改进
- package com.sofwin.singletonDemo;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-饿汉式
- *
- * 要点:
- * 1.构造器私有化
- * 2.定义静态常量存储对象唯一实例
- * 3.通过getter方法获取实例对象
- */
- public class Singleton01 {
-
- /**
- * 构造器私有化
- */
- private static final Singleton01 SINGLETON_01 = new Singleton01();
-
-
- private Singleton01() {
- //防止反射破坏单例
- if (SINGLETON_01 !=null) {
- throw new RuntimeException("单例对象不能重复创建");
- }
- System.out.println("private Singleton01");
- }
-
- public static Singleton01 getSingleton01() {
- return SINGLETON_01;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
- }
2、反序列化破坏单例
Singleton01类要实现Serializable
- package com.sofwin.singletonDemo;
-
- import java.io.Serializable;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-饿汉式
- *
- * 要点:
- * 1.构造器私有化
- * 2.定义静态常量存储对象唯一实例
- * 3.通过getter方法获取实例对象
- */
- public class Singleton01 implements Serializable {
-
- /**
- * 构造器私有化
- */
- private static final Singleton01 SINGLETON_01 = new Singleton01();
-
-
- private Singleton01() {
- //防止反射破坏单例
- if (SINGLETON_01 !=null) {
- throw new RuntimeException("单例对象不能重复创建");
- }
- System.out.println("private Singleton01");
- }
-
- public static Singleton01 getSingleton01() {
- return SINGLETON_01;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
- }
测试代码
- package com.sofwin.singletonDemo;
-
- import org.junit.Test;
-
- import java.io.*;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:09
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式的测试
- */
- public class SingletonTest {
-
- //单例模式-饿汉式
- @Test
- public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
- //先判断是否类初始化的时候就创建对象了
- Singleton01.otherMethod();
- System.out.println("=================");
- Singleton01 singleton01 = Singleton01.getSingleton01();
- Singleton01 singleton02 = Singleton01.getSingleton01();
- System.out.println(singleton01);
- System.out.println(singleton02);
- // System.out.println("反射暴力破解");
- // SingletonTest.reflection(Singleton01.class);
- System.out.println("反序列化破解");
- SingletonTest.serialzable(singleton02);
- }
-
- /**
- * 反射破坏单例pos
- * @param clazz 类对象
- */
- public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor();
- //暴力破解
- declaredConstructor.setAccessible(true);
- //通过反射创建实例对象
- Object o = declaredConstructor.newInstance();
- System.out.println(o);
- }
-
- /**
- * 反序列破解单例模式
- * @param instance 对象
- */
- public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
- //将对象读取到baos中
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(instance);
- //通过字节数组获取对象
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
- Object o = ois.readObject();
- System.out.println(o);
- }
- }
改进
- package com.sofwin.singletonDemo;
-
- import java.io.Serializable;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-饿汉式
- *
- * 要点:
- * 1.构造器私有化
- * 2.定义静态常量存储对象唯一实例
- * 3.通过getter方法获取实例对象
- */
- public class Singleton01 implements Serializable {
-
- /**
- * 构造器私有化
- */
- private static final Singleton01 SINGLETON_01 = new Singleton01();
-
-
- private Singleton01() {
- //防止反射破坏单例
- if (SINGLETON_01 !=null) {
- throw new RuntimeException("单例对象不能重复创建");
- }
- System.out.println("private Singleton01");
- }
-
- public static Singleton01 getSingleton01() {
- return SINGLETON_01;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
-
- /**
- * 解决反序列化
- * @return 实例对象
- *
- */
- public Object readResolve() {
- return SINGLETON_01;
- }
-
-
- }
这里 readResolve() 方法的解释
简而言之,当我们通过反序列化readObejct方法获取对象的时候,会去寻找readResolve()方法,如果该方法不存在则直接返回新对象,如果该方法存在则按照该方法的内容返回对象,以确保如果我们之前实例化了单例对象,就返回该对象。
为什么要使用功能readResolve()方法就解决了?
这里看一下重点代码,readOrdinaryObject
方法的代码片段:
isInstantiable
:如果一个serializable/externalizable的类可以在运行时被实例化,那么该方法就返回true。针对serializable和externalizable我会在其他文章中介绍。
desc.newInstance
:该方法通过反射的方式调用无参构造方法新建一个对象。
然后关键是下面的代码
- if (obj != null &&
- handles.lookupException(passHandle) == null &&
- desc.hasReadResolveMethod())
- {
- Object rep = desc.invokeReadResolve(obj);
- if (unshared && rep.getClass().isArray()) {
- rep = cloneArray(rep);
- }
- if (rep != obj) {
- // Filter the replacement object
- if (rep != null) {
- if (rep.getClass().isArray()) {
- filterCheck(rep.getClass(), Array.getLength(rep));
- } else {
- filterCheck(rep.getClass(), -1);
- }
- }
- handles.setObject(passHandle, obj = rep);
- }
- }
hasReadResolveMethod
:如果实现了serializable 或者 externalizable接口的类中包含readResolve
则返回true
invokeReadResolve
:通过反射的方式调用要被反序列化的类的readResolve方法。
所以,原理也就清楚了,主要在Singleton中定义readResolve方法,并在该方法中指定要返回的对象的生成策略,就可以防止单例被破坏。
3、Unsafe破坏单例
- package com.sofwin.singletonDemo;
-
- import org.junit.Test;
- import org.springframework.objenesis.instantiator.util.UnsafeUtils;
-
- import java.io.*;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:09
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式的测试
- */
- public class SingletonTest {
-
- //单例模式-饿汉式
- @Test
- public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
- //先判断是否类初始化的时候就创建对象了
- Singleton01.otherMethod();
- System.out.println("=================");
- Singleton01 singleton01 = Singleton01.getSingleton01();
- Singleton01 singleton02 = Singleton01.getSingleton01();
- System.out.println(singleton01);
- System.out.println(singleton02);
- // System.out.println("反射暴力破解");
- // SingletonTest.reflection(Singleton01.class);
- // System.out.println("反序列化破解");
- // SingletonTest.serialzable(singleton02);
- System.out.println("unsafe");
- unsafe(singleton01.getClass());
- }
-
- /**
- * 反射破坏单例pos
- * @param clazz 类对象
- */
- public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor();
- //暴力破解
- declaredConstructor.setAccessible(true);
- //通过反射创建实例对象
- Object o = declaredConstructor.newInstance();
- System.out.println(o);
- }
-
- /**
- * 反序列破解单例模式
- * @param instance 对象
- */
- public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
- //将对象读取到baos中
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(instance);
- //通过字节数组获取对象
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
- Object o = ois.readObject();
- System.out.println(o);
- }
-
- /**
- * 使用spring的工具类在jdk底层来访问,无序调用构造方法
- * @param clazz
- * @throws InstantiationException
- */
- public static void unsafe(Class clazz) throws InstantiationException {
- Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
- System.out.println(o);
- }
- }
这个是无法解决的
代码
- package com.sofwin.singletonDemo;
-
- import sun.dc.pr.PRError;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 11:34
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式 --枚举饿汉式
- */
- public enum Singleton02 {
- INSTANCE;
-
- private Singleton02() {
- System.out.println("private Singleton02");
- }
-
- public static Singleton02 getInstance() {
- return INSTANCE;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
-
- @Override
- public String toString() {
- //Integer.toHexString 转换为16进制
- return getClass().getName()+"@"+Integer.toHexString(hashCode());
- }
- }
测试
- package com.sofwin.singletonDemo;
-
- import org.junit.Test;
- import org.springframework.objenesis.instantiator.util.UnsafeUtils;
-
- import java.io.*;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:09
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式的测试
- */
- public class SingletonTest {
-
- //单例模式-饿汉式
- @Test
- public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
- //先判断是否类初始化的时候就创建对象了
- Singleton01.otherMethod();
- System.out.println("=================");
- Singleton02 singleton01 = Singleton02.INSTANCE;
- Singleton02 singleton02 = Singleton02.INSTANCE;
- System.out.println(singleton01);
- System.out.println(singleton02);
- //1、反射不存在,枚举没有无参构造器
- // System.out.println("反射暴力破解");
- // SingletonTest.reflection(Singleton02.class);
- //2、反序列化不存在,readObject的时候会进行判断 ,如果是枚举类有特殊处理
- // System.out.println("反序列化破解");
- // SingletonTest.serialzable(singleton02);
- //3、jdk这个是无法避免的,是可以破坏的
- // System.out.println("unsafe");
- // unsafe(singleton01.getClass());
- }
-
- /**
- * 反射破坏单例pos
- * @param clazz 类对象
- */
- public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor();
- //暴力破解
- declaredConstructor.setAccessible(true);
- //通过反射创建实例对象
- Object o = declaredConstructor.newInstance();
- System.out.println(o);
- }
-
- /**
- * 反序列破解单例模式
- * @param instance 对象
- */
- public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
- //将对象读取到baos中
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(instance);
- //通过字节数组获取对象
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
- Object o = ois.readObject();
- System.out.println(o);
- }
-
- /**
- * 使用spring的工具类在jdk底层来访问,无序调用构造方法
- * @param clazz
- * @throws InstantiationException
- */
- public static void unsafe(Class clazz) throws InstantiationException {
- Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
- System.out.println(o);
- }
- }
1、反射无法破坏枚举类单例
枚举没有无参构造
修改成有参构造
- /**
- * 反射破坏单例pos
- * @param clazz 类对象
- */
- public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class,int.class);
- //暴力破解
- declaredConstructor.setAccessible(true);
- //通过反射创建实例对象
- Object o = declaredConstructor.newInstance("OTHER",1);
- System.out.println(o);
- }
2、反序列话也无法破坏枚举类的单例
3、Unsafe是可以破坏的
代码
- package com.sofwin.singletonDemo;
-
- import java.io.Serializable;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-懒汉式
- *
- * 要点:
- * 1.构造器私有化
- * 2.定义静态常量存储对象唯一实例
- * 3.通过getter方法获取实例对象
- */
- public class Singleton03 implements Serializable {
-
- /**
- * 构造器私有化
- */
- private static Singleton03 instance = null;
-
-
- private Singleton03() {
- //防止反射破坏单例
- if (instance !=null) {
- throw new RuntimeException("单例对象不能重复创建");
- }
- System.out.println("private Singleton01");
- }
-
- public static Singleton03 getSingleton01() {
- if (instance == null) {
- instance = new Singleton03();
- }
- return instance;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
-
- /**
- * 解决反序列化
- * @return 实例对象
- *
- */
- public Object readResolve() {
- return instance;
- }
-
-
- }
测试
- package com.sofwin.singletonDemo;
-
- import org.junit.Test;
- import org.springframework.objenesis.instantiator.util.UnsafeUtils;
-
- import java.io.*;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.InvocationTargetException;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:09
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式的测试
- */
- public class SingletonTest {
-
- //单例模式-饿汉式
- @Test
- public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
- //先判断是否类初始化的时候就创建对象了
- Singleton03.otherMethod();
- System.out.println("=================");
- Singleton03 singleton01 = Singleton03.getSingleton01();
- Singleton03 singleton02 = Singleton03.getSingleton01();
- System.out.println(singleton01);
- System.out.println(singleton02);
- //1、反射可以破坏单例
- // System.out.println("反射暴力破解");
- // SingletonTest.reflection(Singleton03.class);
- //2、反序列化也可以破坏
- // System.out.println("反序列化破解");
- // SingletonTest.serialzable(singleton02);
- //3、jdk这个是无法避免的,是可以破坏的
- // System.out.println("unsafe");
- // unsafe(singleton01.getClass());
- }
-
- /**
- * 反射破坏单例pos
- * @param clazz 类对象
- */
- public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- //获取无参构造方法
- Constructor declaredConstructor = clazz.getDeclaredConstructor();
- //暴力破解
- declaredConstructor.setAccessible(true);
- //通过反射创建实例对象
- Object o = declaredConstructor.newInstance();
- System.out.println(o);
- }
-
- /**
- * 反序列破解单例模式
- * @param instance 对象
- */
- public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
- //将对象读取到baos中
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(instance);
- //通过字节数组获取对象
- ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
- Object o = ois.readObject();
- System.out.println(o);
- }
-
- /**
- * 使用spring的工具类在jdk底层来访问,无序调用构造方法
- * @param clazz
- * @throws InstantiationException
- */
- public static void unsafe(Class clazz) throws InstantiationException {
- Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
- System.out.println(o);
- }
- }
反射、序列化和unsafe都可以破坏
但是这样都会导致一个问题多线程的情况会出现错误情况 (之前,懒汉式的常量和静态代码块中的代码,其实是jvm底层维护的是线程安全的,无序考虑) 因为这个是方法中创建实例就会出现线程安全的问题
测试代码
- public class SingletonTest {
-
- public static void main(String[]args){
- new Thread( new Runnable() {
- @Override
- public void run() {
- Singleton03 singleton01 = Singleton03.getSingleton01();
- System.out.println(singleton01);
- }
- }).start();
-
- new Thread( new Runnable() {
- @Override
- public void run() {
- Singleton03 singleton01 = Singleton03.getSingleton01();
- System.out.println(singleton01);
- }
- }).start();
- }
- }
正常应该是这种情况:
但是多运行几次,也会出现这样的情况:
造成的这种情况的结果是问题是:
这个时候就出现了DCL懒汉式(双检锁的懒汉式)
- package com.sofwin.singletonDemo;
-
- import java.io.Serializable;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-懒汉式
- *
- * 要点:
- * 1.构造器私有化
- * 2.定义静态常量存储对象唯一实例
- * 3.通过getter方法获取实例对象
- */
- public class Singleton04 implements Serializable {
-
- /**
- * 构造器私有化
- */
- //这里加入valatile是保证这个变量是有序的,可见的
- //防止指令重排序,在赋值语句后加入一个内存屏障,防止之前的赋值操作,进行重新排序
- private static volatile Singleton04 instance = null;
-
-
-
- private Singleton04() {
- //防止反射破坏单例
- if (instance !=null) {
- throw new RuntimeException("单例对象不能重复创建");
- }
- System.out.println("private Singleton01");
- }
-
- public static Singleton04 getSingleton01() {
-
- if (instance == null) {
- synchronized (Singleton04.class){
- if (instance == null) {
- instance = new Singleton04();
- }
- }
- }
- return instance;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
-
- /**
- * 解决反序列化
- * @return 实例对象
- *
- */
- public Object readResolve() {
- return instance;
- }
-
-
- }
这个代码可以这样理解:
public static Singleton04 getSingleton01() {
if (instance == null) {
synchronized (Singleton04.class){
if (instance == null) {
instance = new Singleton04();
}
}
//里面这一块是进行加锁放在出现上面的情况
//外面的if判断是进行代码的优化
//我们这个线程锁只是还没创建对象实例的情况出现,因此加上if后
//我们就保证了后序的调用无需进行加锁操作,加快了效率
}
return instance;
}
- package com.sofwin.singletonDemo;
-
- import java.io.Serializable;
-
- /**
- * @packageName: com.sofwin.singletonDemo
- * @author: wentao
- * @date: 2022/11/21 10:00
- * @version: 1.0
- * @email 1660420659@qq.com
- * @description: 单例模式-内部类懒汉式
- *
- * 要点:
- * 内部类不会随着玩不类的加载而初始化
- * 它是单独进行初始化和加载的,并且静态成员的赋值,都是在静态代码块中的,是底层保证线程安全的
- * 只有调用内部类的类变量的时候,才进行初始化,实现懒汉式模式
- */
- public class Singleton05 implements Serializable {
-
- /**
- * 构造器私有化
- */
- private Singleton05() {
- System.out.println("private Singleton01");
- }
-
- private static class Holder {
- static Singleton05 instance = new Singleton05();
- }
-
- public static Singleton05 getSingleton01() {
- return Holder.instance;
- }
-
- /**
- * 通过调用静态方法,实现类的初始化
- * 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
- */
- public static void otherMethod() {
- System.out.println("判断是懒汉式还是饿汉式");
- }
-
-
-
-
- }
System的gc() 垃圾回收机制中的Runtime.getRuntime().gc()
- public class Runtime {
- private static Runtime currentRuntime = new Runtime();
-
- /**
- * Returns the runtime object associated with the current Java application.
- * Most of the methods of class
Runtime
are instance - * methods and must be invoked with respect to the current runtime object.
- *
- * @return the
Runtime
object associated with the current - * Java application.
- */
- public static Runtime getRuntime() {
- return currentRuntime;
- }
-
- /** Don't let anyone else instantiate this class */
- private Runtime() {}
Comparator的naturalOrder()
System中的cons成员变量
Collections中的emptyListInterator()