首页 > 编程语言 >Java笔记(八):单例模式

Java笔记(八):单例模式

时间:2023-05-25 14:23:11浏览次数:47  
标签:Singleton Java getInstance 笔记 instance 实例 static 单例 public

懒汉式

懒汉式单例模式在第一次调用的时候进行实例化。

1. 适用于单线程环境(不推荐)

此方式在单线程的时候工作正常,但在多线程的情况下就有问题了。如果两个线程同时运行到判断instance是否为null的if语句,并且instance的确没有被创建时,那么两个线程都会创建一个实例,此时类型Singleton就不再满足单例模式的要求了。

public class Singleton {
	private static Singleton instance = null;
  
	private Singleton() {}
  
	public static Singleton getInstance() {
		if (null == instance) {
			instance = new Singleton();
		}
		return instance;
	}
}

2. 适用于多线程环境,但效率不高(不推荐)

为了保证在多线程环境下我们还是只能得到该类的一个实例,只需要在getInstance()方法加上同步关键字sychronized,就可以了。但每次调用getInstance()方法时都被synchronized关键字锁住了,会引起线程阻塞,影响程序的性能。

public static synchronized Singleton getInstance() {
	if (instance == null) {
		instance = new Singleton();
	}
	return instance;
}

3. 双重检验锁

为了在多线程环境下,不影响程序的性能,不让线程每次调用getInstance()方法时都加锁,而只是在实例未被创建时再加锁,在加锁处理里面还需要判断一次实例是否已存在。

public static Singleton getInstance() {
	// 先判断实例是否存在,若不存在再对类对象进行加锁处理
	if (instance == null) {
		synchronized (Singleton.class) {
			if (instance == null) {
				instance = new Singleton();
			}
		}
	}
	return instance;
}

4. 静态内部类方式(推荐)

加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生。 由于在调用 StaticSingleton.getInstance() 的时候,才会对单例进行初始化,而且通过反射,是不能从外部类获取内部类的属性的;由于静态内部类的特性,只有在其被第一次引用的时候才会被加载,所以可以保证其线程安全性。
总结:

  • 优势:兼顾了懒汉模式的内存优化(使用时才初始化)以及饿汉模式的安全性(不会被反射入侵)
  • 劣势:需要两个类去做到这一点,虽然不会创建静态内部类的对象,但是其 Class 对象还是会被创建,而且是属于永久带的对象
public class StaticSingleton {
	private StaticSingleton() {}
  
	// 获取实例
	public static StaticSingleton getInstance() {
		return StaticSingletonHolder.instance;
	}

	// 一个私有的静态内部类,用于初始化一个静态final实例
	private static class StaticSingletonHolder {
		private static final StaticSingleton instance = new StaticSingleton();
	}

	public void methodA() {}

	public void methodB() {}

	public static void main(String[] args) {
		StaticSingleton.getInstance().methodA();
		StaticSingleton.getInstance().methodB();
	}
}

饿汉式

饿汉式单例类:在类初始化时,已经自行实例化。

1. 饿汉式

public class Singleton {
	private static final Singleton instance = new Singleton();

	private Singleton() {}

	public static Singleton getInstance() {
		return instance;
	}
}

2.枚举方式(推荐)

创建枚举默认就是线程安全的,所以不需要担心double checked locking,而且还能防止反序列化导致重新创建新的对象。保证只有一个实例(即使使用反射机制也无法多次实例化一个枚举量)。

public class Singleton {
	public static void main(String[] args) {
		Single single = Single.SINGLE;
		single.print();
	}

	enum Single {
		SINGLE;

		private Single() {}

		public void print() {
			System.out.println("hello world");
		}
	}
}

标签:Singleton,Java,getInstance,笔记,instance,实例,static,单例,public
From: https://www.cnblogs.com/Bota5ky/p/17431073.html

相关文章

  • 碎片化学习前端之JavaScript(for...in 和 Object.keys() 的区别)
    前言JavaScript中遍历对象的方式主要有:for...in和Object.keys()两种方式。for...inletobj={name:'ming',age:18,}obj[Symbol('hello')]='world'obj.__proto__={gender:'man',job:'font-end'}f......
  • C++ MFC 学习笔记+小型通讯录系统实现
    [MFC最详细入门教程](https://blog.csdn.net/freeking101/article/details/101013627?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168387812916782427455065%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=1683878129167824274550......
  • 【笔记】杂项问题随手记
    C语言中<stdio.h>与“stdio.h“的区别:<stdio.h>表示在包含文件目录中去查找(包含文件目录是由用户在设置环境时设置的),而不再源文件目录中查找。"stdio.h"表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。<stdio.h>用于引入标准库函数头文件,它是一个标准头文件,通常......
  • Java序列化和反序列化
    序列化和反序列化的定义*Java序列化就是指把Java对象转换为字节序列的过程*Java反序列化就是指把字节序列恢复为Java对象的过程。 以下是我们常见的一行代码:privatestaticfinallongserialVersionUID=1L;关于这行代码,这是java源码中的一段话:如果可序列化类没有显......
  • Unity3D高级编程主程手记 学习笔记三:数据表与程序
    什么是数据表?有什么用?数据表相当于一个只读的外部数据库,用来存储着游戏内的各种数据项。数据表是连接了美术、设计策划和程序的桥梁。艺术家用它来配置效果,设计师用它来调整游戏内数值平衡,程序员用它来判断逻辑,所以数据表的意义十分重大。 数据在游戏中存储有几种方式,......
  • 归并排序Java版(图文并茂思路分析)
    归并排序工作原理:工作原理是将一个大问题分解成小问题,再将小问题分解成更小的。(乍一看就觉得是像一个递归)就像下图这样。然后不断的将其一份为二,分解成更小的排序。我们设一个函数叫MergeSort(arr,l,r)意思就是将arr数组下标为[l,r]之间的数进行排序。那么就开始不断的调用自......
  • XML和javaConfig
    1. 为什么要使用 Spring Boot  11. 因为Spring, SpringMVC 需要使用的大量的配置文件 (xml文件)还需要配置各种对象,把使用的对象放入到spring容器中才能使用对象需要了解其他框架配置规则。2. SpringBoot 就相当于 不需要配置文件的Spring+SpringMVC。 常用的框架和第三......
  • 003 Python 学习笔记
    """-----------bool运算符、比较运算符学习----------bool运算符Ture/False,注:Ture本质上是一个数字即1,False是0使用方式:bool或使用比较运算符(>、<、=、>=、<=、==)字符串可拼接,bool不可拼接"""isSuccess=Trueprint(f"isSuccess={isSuccess}")isOk=10......
  • java arrays arraycopy 复制数组
    publicstaticvoidmain(Stringargs[]){int[]source={1,2,3,4,5,6,7};int[]target=newint[5];System.arraycopy(source,0,target,0,5);//6,7超出5的长度,被省略了System.out.println(Arrays.toString(target));for(......
  • 学习笔记-JVM
    JVM的位置JVM是运行在操作系统上的虚拟机,存在于JRE当中JVM的类型HotSpotSun公司用的基本都是这个JRockitBEAJ9VMIBMJVM的体系结构本地方法接口JNIJNI的作用拓展java的使用,融合不同的编程语言为java所用最初是C/C++因为最初java诞生......