type
status
date
slug
summary
tags
category
icon
password
一、概念
确保
一个类只有一个实例
,并提供该实例的全局访问点
。以一个私有构造函数
、一个私有静态变量
、一个公有静态函数
来实现。单例模式是一种对象创建型模式,主要关键点是某个类只能有一个实例、这个类必须自己创建这个实例、必须向整个系统提供这个实例。- 优点:提供了唯一实例的受控访问,节约系统资源(对于一些需要频繁创建和销毁的对象)
- 缺点:没有接口,不能继承。一定程度上违背了单一职责原则(单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,可能会包含一些业务代码)
- 使用场景:要求生产唯一序列号,WEB中的计数器(不用每次刷新都在数据库中加一次,用单例先缓存),创建一个对象需要消耗的资源过多(如I/O与数据库的连接等)
注意
:getInstance()
需要使用同步锁synchronized(Singletion.class)防止多线程同时进入造成instance被多次实例化。
![notion image](https://oss.zhulinz.top/newImage/202210121629537.png?t=16e5cb3c-15b7-4adb-8c9e-d73d924bc8ca)
二、饿汉式(推荐)
天生的线程安全单例模式,类加载的时候就已经进行实例化了,在
getInstance()
方法之前实例就存在了,多线程情况下是安全的。但容易产生垃圾对象。基于
classloader
机制避免了多线程的同步问题,不过,instance
在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance
方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance
显然没有达到lazy loading
的效果。- 优点:线程安全,没有加锁,执行效率会提高。
- 缺点:实例在类加载的时候就初始化,可能存在浪费内存的情况
三、懒汉式(线程不安全_不推荐)
懒加载模式,最基本的实现方式,最大的问题是不支持多线程的情况。由于
getInstance()
没有加锁,在多线程的情况下可能会同时调用该方法,创建多个实例。四、懒汉式(线程安全,同步方法_不推荐)
解决了线程安全的问题,但是效率太低,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。而该方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行,方法进行同步效率太低
五、懒汉式(线程安全,同步代码块)
六、双检锁/双重校验锁(DCL,即 double-checked locking_推荐)
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
getInstance()
的性能对应用程序很关键。实例化代码只执行了一次,后面再次访问时,判断if(instance==null),直接return实例化对象,也避免的反复进行方法同步。七、静态内部类
可以达到和双检锁方式一样的功效,实现更简单。此方式是只适用于对静态域使用延迟初始化,双检锁可在实例语需要延迟初始化时使用。
这种方式同样利用了
classLoader
机制来保证初始化instance
时只有一个线程。该方式是将instance
的初始化方式放在静态内部类中,类加载的时候,静态内部类会被装载了,但是instance
并不一定被初始化。只有通过显式调用 getInstance()
方法时,才会显式装载 SingleToInstance
类,从而实例化 instance
。类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
八、枚举
这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
这种方式是
《Effective Java》作者(Josh Bloch)
提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。不能通过 reflection attack 来调用私有构造方法。- Author:拾荒😂
- URL:https://blog.zhulinz.top//article/singletondesignpattern
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!