Java中如何实现单例模式:双重校验锁、内部静态类、枚举方式?

2026-05-22 12:401阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计680个文字,预计阅读时间需要3分钟。

Java中如何实现单例模式:双重校验锁、内部静态类、枚举方式?

================================

©Copyright 蕃薯耀2022-05-20

www.cnblogs.com/fanshuyao/

一、饿汉模式

public class Hunger { /** * 增加final关键字,避免被修改 */ private static final Hunger hunger = new Hunger(); /** * 私有化,避免创建对象 */ private Hunger() {}; /** * 提供获取对象的方法 * @return */ public static Hunger get() { return hunger; } }

二、饿汉模式(静态块)

可以通过配置文件对实例进行初始化

import lqy.utils.PropertiesUtils; public class HungerStatic { private static final HungerStatic hungerStatic; private String name; /** * 私有化,避免创建对象 */ private HungerStatic(String name) { this.name = name; }; static { String name = PropertiesUtils.readKeyValue("config.properties", "name"); hungerStatic = new HungerStatic(name); } /** * 提供获取对象的方法 * @return */ public static HungerStatic get() { //System.out.println(hungerStatic); return hungerStatic; } /* @Override public String toString() { return "HungerStatic [name=" + name + "]"; } */ }

三、懒汉模式 - 同步方法

public class LazySafe { private static LazySafe lazySafe; private LazySafe() {} public static synchronized LazySafe get() { if(lazySafe == null) { lazySafe = new LazySafe(); } return lazySafe; } }

四、懒汉模式 - 同步块

public class LazySync { /** * 需要加volatile防止指令重排 */ private static volatile LazySync lazySync; private LazySync() {} public static LazySync get() { synchronized (LazySync.class) { if(lazySync == null) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } lazySync = new LazySync(); } } return lazySync; } }

Java中如何实现单例模式:双重校验锁、内部静态类、枚举方式?

五、懒汉模式 -双重判断

public class LazySyncDouble { /** * 需要加volatile防止指令重排 */ private static volatile LazySyncDouble lazySyncDouble; private LazySyncDouble() {} public static LazySyncDouble get() { if(lazySyncDouble == null) { synchronized (LazySyncDouble.class) { if(lazySyncDouble == null) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } lazySyncDouble = new LazySyncDouble(); } } } return lazySyncDouble; } }

六、懒汉模式 -内部类

/** * Inner是一个内部静态类,当外部类 LazyInner 被加载的时候,并不会创建 Inner实例对象。 * 只有当调用 get() 方法时,Inner才会被加载,这个时候才会创建 instance。 * instance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。 * 所以,这种实现方法既保证了线程安全,又能做到延迟加载。 * @author islee * */ public class LazyInner { private LazyInner() {} /** * 静态内部类 * */ private static class Inner{ private static final LazyInner lazyInner = new LazyInner(); } public static LazyInner get() { return Inner.lazyInner; } }

七、枚举

最安全,能预防反射和反序列化的安全问题

/** * Java虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次。 * [最安全],其他的会存在反射和反序列化的安全问题 * */ public class SingletonEnum { private SingletonEnum() {} private enum SingletonHolder { INSTANCE; private final SingletonEnum singletonEnum; private SingletonHolder() { singletonEnum = new SingletonEnum(); } private SingletonEnum get() { return singletonEnum; } } public static SingletonEnum get() { return SingletonHolder.INSTANCE.get(); } }

测试:

import lqy.design.singleton.SingletonEnum; public class SingletonEnumTest { public static void singletonEnum() { long startTime = System.currentTimeMillis(); for(int i=0; i<15; i++){ new Thread(()-> { System.out.println(SingletonEnum.get()); }).start(); } long endTime = System.currentTimeMillis(); System.out.println("耗时:" + (endTime - startTime)); } public static void main(String[] args) { singletonEnum(); } }

(时间宝贵,分享不易,捐赠回馈,^_^)

================================

©Copyright 蕃薯耀2022-05-20

www.cnblogs.com/fanshuyao/

今天越懒,明天要做的事越多。

本文共计680个文字,预计阅读时间需要3分钟。

Java中如何实现单例模式:双重校验锁、内部静态类、枚举方式?

================================

©Copyright 蕃薯耀2022-05-20

www.cnblogs.com/fanshuyao/

一、饿汉模式

public class Hunger { /** * 增加final关键字,避免被修改 */ private static final Hunger hunger = new Hunger(); /** * 私有化,避免创建对象 */ private Hunger() {}; /** * 提供获取对象的方法 * @return */ public static Hunger get() { return hunger; } }

二、饿汉模式(静态块)

可以通过配置文件对实例进行初始化

import lqy.utils.PropertiesUtils; public class HungerStatic { private static final HungerStatic hungerStatic; private String name; /** * 私有化,避免创建对象 */ private HungerStatic(String name) { this.name = name; }; static { String name = PropertiesUtils.readKeyValue("config.properties", "name"); hungerStatic = new HungerStatic(name); } /** * 提供获取对象的方法 * @return */ public static HungerStatic get() { //System.out.println(hungerStatic); return hungerStatic; } /* @Override public String toString() { return "HungerStatic [name=" + name + "]"; } */ }

三、懒汉模式 - 同步方法

public class LazySafe { private static LazySafe lazySafe; private LazySafe() {} public static synchronized LazySafe get() { if(lazySafe == null) { lazySafe = new LazySafe(); } return lazySafe; } }

四、懒汉模式 - 同步块

public class LazySync { /** * 需要加volatile防止指令重排 */ private static volatile LazySync lazySync; private LazySync() {} public static LazySync get() { synchronized (LazySync.class) { if(lazySync == null) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } lazySync = new LazySync(); } } return lazySync; } }

Java中如何实现单例模式:双重校验锁、内部静态类、枚举方式?

五、懒汉模式 -双重判断

public class LazySyncDouble { /** * 需要加volatile防止指令重排 */ private static volatile LazySyncDouble lazySyncDouble; private LazySyncDouble() {} public static LazySyncDouble get() { if(lazySyncDouble == null) { synchronized (LazySyncDouble.class) { if(lazySyncDouble == null) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } lazySyncDouble = new LazySyncDouble(); } } } return lazySyncDouble; } }

六、懒汉模式 -内部类

/** * Inner是一个内部静态类,当外部类 LazyInner 被加载的时候,并不会创建 Inner实例对象。 * 只有当调用 get() 方法时,Inner才会被加载,这个时候才会创建 instance。 * instance 的唯一性、创建过程的线程安全性,都由 JVM 来保证。 * 所以,这种实现方法既保证了线程安全,又能做到延迟加载。 * @author islee * */ public class LazyInner { private LazyInner() {} /** * 静态内部类 * */ private static class Inner{ private static final LazyInner lazyInner = new LazyInner(); } public static LazyInner get() { return Inner.lazyInner; } }

七、枚举

最安全,能预防反射和反序列化的安全问题

/** * Java虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次。 * [最安全],其他的会存在反射和反序列化的安全问题 * */ public class SingletonEnum { private SingletonEnum() {} private enum SingletonHolder { INSTANCE; private final SingletonEnum singletonEnum; private SingletonHolder() { singletonEnum = new SingletonEnum(); } private SingletonEnum get() { return singletonEnum; } } public static SingletonEnum get() { return SingletonHolder.INSTANCE.get(); } }

测试:

import lqy.design.singleton.SingletonEnum; public class SingletonEnumTest { public static void singletonEnum() { long startTime = System.currentTimeMillis(); for(int i=0; i<15; i++){ new Thread(()-> { System.out.println(SingletonEnum.get()); }).start(); } long endTime = System.currentTimeMillis(); System.out.println("耗时:" + (endTime - startTime)); } public static void main(String[] args) { singletonEnum(); } }

(时间宝贵,分享不易,捐赠回馈,^_^)

================================

©Copyright 蕃薯耀2022-05-20

www.cnblogs.com/fanshuyao/

今天越懒,明天要做的事越多。