所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在。类似Spring中的IOC 配置,bean实例化默认都是单例模式的。
单例的四种写法:
1.饿汉式单例
//饿汉式 public class Singleton{ //1.私有的唯一的静态实例变量,在类加载的时候就创建好单例对象 private static final Singletion instance= new Singleton(); //2.私有的构造函数,确保不能在类的外部访问该类的构造函数 private Singleton{} //3.通过静态工厂方法返回类的唯一实例 private static Singletion getInstance(){ return instance; } }
优点:此写法是线程安全的
缺点:会增大初始化类和创建对象的开销
2.懒汉式
public class Singleton { //1.一个私有的指向自己的静态变量 private static Singleton instance = null; // 2.私有的构造方法,保证不能从外部创建对象 private Singleton{} //3.真正获取实例的时候才进行初始化,如果多线程访问 synchronized会阻塞其他线程 public static synchronized Singleton getInstance() { if (instance == null) instance = new Singleton(); // lazy load return instance; } }
优点: 延时加载,只有在使用的时候进行初始化
问题:同步锁粒度在多线程进行获取实例的时候会出现阻塞,加大了因锁竞争的性能开销
3.double-check双重检查锁定
public class Singleton { //1.volatile保证可见性 private static volatile Singleton instance = null; // 2.私有的构造方法,保证不能从外部创建对象 private Singleton{} public static Singleton getInstance() { //3.instance使用volatile标识可以保证所有线程访问同一共享变量的可见性问题 if (instance == null) {// double check (jdk1.5+) //4.synchronized虽然保证了原子性,但不能保证 同步方法里面的顺序性 //5. instance = new Singletion(),其实由三步组成 // 1).分配对象内存空间 2).初始化对象 3).设置instance指向刚分配的内存地址 //6.由于不同cpu的内核,JMM重排序粒度不一样,instance在第2,3步见可能会被重排序 // 执行过程中instance不为null,但获取对象 并不是真正赋值对象(旧值或空值) synchronized (Singleton.class) if (instance == null){ instance = new Singleton(); } } return instance; } }
优点: 用双重验证的方式,降低因多线程因为同步锁而造成的开销,同步锁保证模块执行的原子性,volatile保证实例可见性
缺点:同步锁模块内部方法体instance = new Singleton();并不是原子性操作(像count++也不是原子性操作) 还是可能造成JIT编译器对代码进行重排序 导致对象的值不正确
4.静态内部类写法
public class Singleton { //1.在第一次被引用时被加载 private static class Holder { // lazy class static final Singleton instance = new Singleton(); } //2.保证不能进行构造 private Singleton(){ } //3.通过静态方法获取 public static Singleton getInstance() { return Holder.instance; } }
优点:线程安全的,且在使用时才会被进行初始化操作,优于上面三种方式
5.单例 枚举写法
public enum SingletonEnum { instance; /* * do something */ public void doSomething(){ System.out.println("do something"); } }
总之,懒汉,恶汉,双重校验锁,静态内部类,枚举。
恶汉:因为加载类的时候就创建实例,所以线程安全(多个ClassLoader存在时例外)。缺点是不能延时加载。
懒汉:需要加锁才能实现多线程同步,但是效率会降低。优点是延时加载。
双重校验锁:麻烦,在当前Java内存模型中不一定都管用,某些平台和编译器甚至是错误的,因为instance = new Singletion()这种代码在不同编译器上的行为和实现方式不可预知。
静态内部类:延迟加载,减少内存开销。因为用到的时候才加载,避免了静态field在单例类加载时即进入到堆内存的permanent代而永远得不到回收的缺点(大多数垃圾回收算法是这样)。
枚举:很好,不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。但是失去了类的一些特性,没有延迟加载,用的人也太少了~~
可参考:
相关推荐
单例模式是软件设计模式中的一种,用于控制类的实例化过程,确保一个类只有一个实例,并提供全局访问点。在Java中,实现单例模式有多种方法,每种方法都有其特点和适用场景。以下是对这六种常见单例模式实现方式的...
在 Java 中,单例模式的写法有好几种,主要有懒汉式单例、饿汉式单例、登记式单例等。 懒汉式单例是一种常见的单例模式实现方式,它在第一次调用的时候实例化自己。下面是懒汉式单例的四种写法: 1、基本懒汉式...
在Unity游戏开发中,单例模式是一种常用的编程设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这种模式在处理需要跨场景共享数据的情况时尤其有用,因为Unity的场景切换可能导致对象被销毁,而单例则...
在Java语言中,实现单例模式主要有以下几种方式: 1. 饿汉式(Eager Initialization) 饿汉式单例模式在类加载的时候就已经进行了实例化,因此它不需要考虑多线程同步的问题。这种方式在类加载时就完成了初始化,...
本文将详细介绍Python中实现单例模式的三种方法:使用装饰器、使用基类以及使用元类,并通过示例代码帮助读者更好地理解和应用这些技术。 #### 二、单例模式简介 单例模式的主要目的是确保一个类只有一个实例,并...
Objective-C中的单例模式是一种设计模式,用于在整个应用程序中确保只有一个特定类的实例存在,并提供一个全局访问点来获取这个实例。单例模式在iOS开发中广泛应用,特别是在管理共享资源、配置设置或网络请求等场景...
需要注意的是,虽然提供了`{providedIn: 'root'}`的方式,但文档中明确说明这个属性并不直接与单例模式有关系,它仅仅是服务提供的一种写法。 在实验中,发现即使服务是懒加载的子模块和组件,当通过`app.module....
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。...2、具体单例模式的几种模式 第一种单例模式 //非线程安全写法 static UserHelper * helper = nil; + (UserH
以下是根据标题和描述中提到的几种设计模式进行的详细解释: 1. **单例模式**:单例模式确保一个类只有一个实例,并提供全局访问点。这种模式在需要频繁创建和销毁对象,且只允许有一个实例的情况下非常有用,如...
【06期】单例模式有几种写法? 【07期】Redis中是如何实现分布式锁的? 【08期】说说Object类下面有几种方法呢? 【09期】说说hashCode() 和 equals() 之间的关系? 【10期】Redis 面试常见问答 【11期】分布式...
1. 单例模式:了解单例模式的几种写法,包括懒汉式、饿汉式、双重检查锁定式等。 2. JDK 中的设计模式:了解 JDK 中的设计模式,包括 IO 中的装饰模式和设配器模式等。 3. 框架中的设计模式:了解常用的设计模式,...
以下是几种实现方式: 1. **懒汉式** ```java public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() {} public static Singleton getSingleton() { ...
1. **单例模式**:通过`Context.getSharedPreferences()`获取的SharedPreferences对象是单例的,意味着在整个应用中只会有一个实例。这样确保了数据的一致性,避免了多个副本可能导致的冲突。 2. **编辑器模式**:`...
这里我们可能会遇到以下几种常见的设计模式: 1. **单例模式**:购物车在整个应用中应当是唯一的,无论用户在哪个页面,购物车的数据都应保持一致。单例模式确保了购物车对象的全局唯一性,避免了多次实例化导致的...
单例模式是一种设计模式,确保一个类只有一个实例,并提供全局访问点。常见的单例实现有饿汉式(静态常量)、懒汉式(线程安全的双重检查锁定)和枚举单例等。 5. **递归算法** 递归是函数或方法在定义时调用自身...
6. **单例模式的几种写法:** 单例模式保证一个类只有一个实例,并提供一个全局访问点。常见的单例实现方式有饿汉式、懒汉式、枚举类型以及利用双重检查锁定机制等。 7. **web.xml加载顺序:** 在Web应用中,web....
10. **设计模式**:常见的23种设计模式,如单例模式、工厂模式、观察者模式等,是解决常见问题的成熟解决方案。 11. **注解(Annotation)**:用于提供元数据,增强代码的功能和可读性。 12. **Lambda表达式**:...
10. **设计模式**:熟悉常见的设计模式,如单例模式、工厂模式、观察者模式等,以及它们在实际开发中的应用。 11. **数据库操作**:SQL基础,ADO.NET或Entity Framework的使用,以及数据库事务处理。 12. **Web...