一篇文章讲清楚单例模式

前言:

做者:韩数html

Github:github.com/hanshuaikan…java

时间:2019-01-26git

Jdk版本:1.8github

定义:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。设计模式

适用范围:

一个全局使用的类频繁地建立与销毁。当某些如打印机程序只须要一个操做实例的时候(多个实例同时调用一台打印机打印文件可能会出现问题)缓存

优/缺点

优势:安全

在内存里只有一个实例,减小了内存的开销,尤为是频繁的建立和销毁实例(好比管理学院首页页面缓存)。多线程

避免对资源的多重占用(好比写文件操做)性能

缺点:spa

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

前提引入:

单例模式是设计模式中较为简单的设计模式之一,同时又在实际的开发过程当中普遍使用的一种设计模式,本次,咱们将从基础版开始,使用4种不一样的方式来实现单例模式。

代码实战:

1.基础版

这种方式实现的单例模式是咱们平常使用较多的设计模式,采用了延迟加载来减小系统资源没必要要的开支,但若是多个线程同时调用 getInstance 方法获取Singleton的实例时,可能会出现问题。

优/缺点:

优势:易于实现

缺点:线程不安全,在多线程下不能正常工做

代码以下:

/*** * * @author 韩数 * 通常单例模式实现,采用延迟加载方式实现 * */

public class Singleton {
	
	private static Singleton uniqueInstance;
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
 
}
复制代码

2.线程安全基础版:

代码以下:

优/缺点:

优势:线程安全,没有加锁,执行效率会高一点

缺点:容易产生垃圾对象,类加载时就初始化,浪费内存

/*** * * @author 韩数 * 经常使用的单例模式实现 * 线程安全,不足之处,可能会损失一部分性能,非延迟加载 * */


public class Singleton {
	
	//在类初始化的时候就实例化对象,因此不存在多线程的安全问题
	private static Singleton uniqueInstance = new Singleton();
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		return uniqueInstance;
	}
}
复制代码
3.线程安全增强版:

优/缺点:

优势:线程安全,延迟加载

缺点:必须加锁,效率比较低

代码以下:

/** * * @author 韩数 * 线程安全方式实现单例模式,缺点是,每次都会调用synchronized的关键字修饰的方法,会损失必定的性能 * */

public class Singleton {
	
	
	private static Singleton uniqueInstance;
 
	private Singleton() {}
 
	//synchronized修饰该方法,保证每次只有一个线程进入该方法,从而避免产生多个Singleton对象实例。
	public static synchronized Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
}

复制代码
4.线程安全旗舰版:

双检锁/双重校验锁(DCL,即 double-checked locking): 能够在保证安全性的状况下,兼顾高性能

优/缺点:

优势:线程安全,延迟加载,执行效率高

缺点:实现难度比前几种稍显复杂

关于 volatile 关键字,感兴趣的伙伴能够去这个博客看一下,写得很是好

www.cnblogs.com/dolphin0520…

代码以下:

/*** * * @author 韩数 * 线程安全,延迟加载方式实现单例模式 * */

public class Singleton {
	
	private volatile static Singleton uniqueInstance;
	
	// 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰以后,那么就具有了两层语义:
	//保证了不一样线程对这个变量进行操做时的可见性,即一个线程修改了某个变量的值,这新值对其余线程来讲是 当即可见的。
	//禁止进行指令重排序。
 
	private Singleton() {}
 
	public static Singleton getInstance() {
		//延迟加载
		if (uniqueInstance == null) {
			//加线程锁
			synchronized (Singleton.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton();
				}
			}
		}
		return uniqueInstance;
	}
}

复制代码

总结:

本篇文章较为简单的阐述了单例模式的优缺点,使用场景,以及4种不一样的实现方式,固然,现实生活中,单例模式的实现绝非只有本文中的4种,若是对单例模式的其余实现方式感兴趣的话,你们能够去互联网上查询相关的资料。

写在最后:

欢迎你们给小星星,您的星星是我写下去的不竭动力!

源码部分请移步本人Github下载:

Github地址:

Github:github.com/hanshuaikan…

参考资料:

菜鸟教程:www.runoob.com/design-patt…

Head frist of 设计模式

相关文章
相关标签/搜索