设计模式:单例模式的写法(基础写法和线程安全写法)

简介: 单例模式的写法很多,先给出一种最基础的写法:(A种写法):package singleton;public class SingletonInstance { private static SingletonInstance mSingletonInstance = null; // 特意将构造函数设置成 private,防止外部使用者new SingletonInstance()。

单例模式的写法很多,先给出一种最基础的写法:

(A种写法):

package singleton;

public class SingletonInstance {

	private static SingletonInstance mSingletonInstance = null;

	// 特意将构造函数设置成 private,防止外部使用者new SingletonInstance()。
	private SingletonInstance() {

	}

	public static SingletonInstance getInstance() {
		if (mSingletonInstance == null) {
			mSingletonInstance = new SingletonInstance();
		}

		return mSingletonInstance;
	}
}

A写法是单例模式最简单、最基础、最清晰的写法,但遗憾的是这种写法是线程不安全的代码写法。假设该类同时在并发N多个线程中被访问被使用、尤其是如果这个类如果涉及到数据库访问等等此类线程安全问题敏感的代码应用场景时,后果将是一场灾难。

但单例模式的A种写法也有其广泛场景:不要求线程安全,没有同步需求且效率优先级高的场景中,推荐使用单例模式的A种写法。


B种写法(线程安全写法1):


package singleton;

public class SingletonInstance {

	private static SingletonInstance mSingletonInstance = null;

	// 特意将构造函数设置成 private,防止外部使用者new SingletonInstance()。
	private SingletonInstance() {

	}

	public static synchronized SingletonInstance getInstance() {
		if (mSingletonInstance == null) {
			mSingletonInstance = new SingletonInstance();
		}

		return mSingletonInstance;
	}
}

单例模式的B种写法其实是在A种写法的基础上的改进,要点是增加了同步机制:synchronized。synchronized ,同步从某种意义上讲其实就是阻塞,阻塞的结果就是任意时刻,只有一个线程可以访问该段同步方法体中的代码。这样被synchronized的代码性能将下降,但达到了线程安全的目的。

B种单例模式的写法,主要是为了解决线程安全。变体很多,变体的目的主要集中在如何增强线程安全的操作性。现举例如下,比如:

B种写法的增强型变体(线程安全写法2):

package singleton;

public class SingletonInstance {

	// 注意!volatile 也不能完全保证线程安全,后面将写关于volatile的文章解释这一点儿。
	// volatile只是增强。
	private static volatile SingletonInstance mSingletonInstance = null;

	// 特意将构造函数设置成 private,防止外部使用者new SingletonInstance()。
	private SingletonInstance() {

	}

	public static SingletonInstance getInstance() {
		if (mSingletonInstance == null) {

			// synchronized (SingletonInstance.class)不必锁住整个方法,只锁住一块代码即可。
			// 和synchronized (this)一样,但因为是static方法,故无法使用this,才使用XXXClass.class
			// synchronized的基本使用原则:尽可能不要锁住大块大块代码(方法体或类),只锁住必需的一小块核心、急需同步的代码段即可,越少越好,越小越好。
			// 要知道,一旦使用synchronized,就意味着代码性能的开销
			synchronized (SingletonInstance.class) {
				if (mSingletonInstance == null)
					mSingletonInstance = new SingletonInstance();
			}
		}

		return mSingletonInstance;
	}
}



相关文章
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
537 15
|
设计模式 运维 监控
并发设计模式实战系列(4):线程池
需要建立持续的性能剖析(Profiling)和调优机制。通过以上十二个维度的系统化扩展,构建了一个从。设置合理队列容量/拒绝策略。动态扩容/优化任务处理速度。检查线程栈定位热点代码。调整最大用户进程数限制。CPU占用率100%
826 0
|
11月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
737 2
|
11月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
535 1
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
407 4
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
313 0
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
800 13
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
281 2
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法

热门文章

最新文章