单例模式四种实现方式
这里的单例模式实现方法都是线程安全的
一般常见的都是两种单例单例实现方法。加了两种,列举如下
- 饿汉式
- 双重检查加锁饿汉式
- 内部类方式
- 枚举单例
下面给出JAVA代码实例
/** * 懒汉式 */ public class Singleton1 { private Singleton1(){} private static final Singleton1 Instance = new Singleton1(); public static Singleton1 getInstance(){ return Instance; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread( ()->{ System.out.println(Singleton1.getInstance().hashCode()); },"A").start(); } } }
/** * 双重检查的饿汉式--线程安全 */ public class Singleton2 { private Singleton2(){} public volatile static Singleton2 Instance; public static Singleton2 getInstance(){ if(Instance==null){ synchronized (Singleton2.class) { try { Thread.currentThread().sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } if(Instance==null){ Instance=new Singleton2(); } } } return Instance; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread( ()->{ System.out.println(Singleton2.getInstance().hashCode()); },"B").start(); } } }
关于DCL的单例模式实现,为什么Instance要加volatile呢?synchronized已经可以保证内存可见性了。
其实是为了防止指令重排序出现问题。Instance = new Singleton2()分为三步。1、堆中申请new Singleton2()的内存空间; 2、对象new Singleton2()进行初始化;3、Instance指向内存地址
如果出现了指令重排序,可以预料到一个比较严重的问题:在第三步先执行后,此时进来另一个线程,它看到Instance不为空之后,可能就直接返回Instance对象,用Instance对象去执行一些操作【注意:此时Instance对象还未完成初始化】,就会出现线程不安全的问题。
/** * 单例类的静态内部类的构造方法只会在调用他的时候触发 * 所以时线程安全的 */ public class Singleton3 { private Singleton3(){} private static class holder{ private final static Singleton3 Instance = new Singleton3(); } public static Singleton3 getInstance(){ return holder.Instance; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(Singleton3.getInstance().hashCode()); },"C").start(); } } }
/** * 推荐方法: * java中,枚举类在编译后,文件中看,就是一个抽象类。所以没有构造方法。所以不存在线程安全问题 * 目前最好的方法,可以避免反序列化 */ public enum Singleton4 { Instance; public void m(){ System.out.println("我是枚举单例"); } public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Singleton4.Instance.hashCode()); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了