文档章节

Java的几种单例模式及特点

Mrling
 Mrling
发布于 2017/09/08 17:10
字数 1199
阅读 55
收藏 1

行业解决方案、产品招募中!想赚钱就来传!>>>

1、Java常见的单例模式(懒汉、饿汉、双重锁模式)


       

    1.1饿汉模式   

public class Singleton_e {
	private static final Singleton_e instance = new Singleton_e();
	private Singleton_e() {
		System.out.println("这是单例模式之:饿汉模式");
	}
	public static Singleton_e getInstance() {
		return instance;
	}
}

    从时间和空间方面分析: 饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。

    从线程安全方面分析:饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。

    1.2懒汉模式

public class Singleton_lan {
	private static Singleton_lan instance = null;
	private Singleton_lan() {
		System.err.println("这是单例模式之:懒汉模式");
	}
	public static synchronized Singleton_lan getInstance() {
		if (instance == null) {
			instance = new Singleton_lan();
		}
		return instance;
	}
}

    从时间和空间方面分析: 懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间。
    从线程安全方面分析:懒汉式从线程安全性上讲,不加同步的懒汉式是线程不安全的,比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题

    1.3双重检查锁模式(DCL)

public class Singleton_shuangchongsuo {
	private static Singleton_shuangchongsuo instance = null;
	private Singleton_shuangchongsuo() {
		System.out.println("这是单例模式之:双重锁模式");//(1)
	}

	public static Singleton_shuangchongsuo getInstance() {
		if (instance == null) {//(2)
			synchronized (instance) {//(3)
				if (instance == null) {//(4)
					instance = new Singleton_shuangchongsuo();//(5)
				}
			}
		}
		return instance;//(6)
	}
}

    双重锁模式简称DCL(double check lock)相当于对懒汉模式进行了增强,保证多线程访问时安全问题(但是不符合happens-before原则,后面会讨论)。

    当然如果直接在Singleton_shuangchongsuo()方法上加锁也可以达到目的,但是这样的话,每次获取实例都要去判断一下是否加锁,造成效率低下。而双重锁只会在特殊情况(第一次创建实例instance时,可能会产生多个实例同时访问的情况下)才会判断锁是哪个,相对效率高。

1.4、用happens-before规则重新审视双重检查锁模式(DCL)

我想简单的用对象创建期间的实际场景来分析一下:(以下是我的个人的理解,所看的资料也是非官方的,不完全保证正确。)

还是看上面1.3双重锁模式的代码,假设线程1执行完(5)时,线程2正好执行到了(2);
看看 new Singleton_shuangchongsuo(); 这个语句的执行过程: 它不是一个原子操作,实际是由多个步骤,我们从我们关注的角度简化一下,简单的认为它主要有2步操作好了:
a) 在内存中分配空间,并将引用指向该内存空间。
b) 执行对象的初始化的逻辑(和操作),完成对象的构建。

此时因为线程1和线程2没有用同步,他们之间不存在“Happens-Before”规则的约束,所以在线程1创建Singleton_shuangchongsuo对象的 a),b)这两个步骤对于线程2来说会有可能出现a)可见,b)不可见
造成了线程2获取到了一个未创建完整的Singleton_shuangchongsuo对象引用,为后边埋下隐患。

改进后的DCL代码:

public class Singleton_lan2 {
	private Singleton_lan2(){
		System.out.println("这是对饿懒模式的的增强,解决由双重锁模式代码未遵循happens-before原则带来的问题");
	}
	private static class InstanceHolder {//1 static 
		private static final  Singleton_lan2 instance = new Singleton_lan2();//2 static 
	}
	public static Singleton_lan2 getInstance(){//3 该static保证不需要实例化Singleton_lan2调用该静态方法
		return InstanceHolder.instance;//通过1、2的static关键字保证可以访问静态类中的静态变量
	}
}

    以上代码是通过静态内部类的方式实现。当getInstance方法第一次被调用的时候,它第一次读取InstanceHolder.instance,导致InstanceHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。

 

 

 

更多相关DCL的修正请参考以下文章:

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

参考文章:http://ifeve.com/java-concurrent-hashmap-1/

更详细解释可以看这里:http://www.javaeye.com/topic/260515?page=1   

 

 

Mrling
粉丝 2
博文 8
码字总数 7639
作品 0
丰台
程序员
私信 提问
加载中
请先登录后再评论。
研究虚拟机--Jikes RVM

Jikes研究虚拟机(Jikes Research Virtual Machine,简称Jikes RVM)是一种成熟的用于执行Java程序的虚拟机,其早期版本与当前版本分别在通用公共许可证(CPL)与Eclipse公共许可证(EPL)下开...

匿名
2013/02/13
1.1K
0
C/C++ 代码文档生成器--cldoc

cldoc 是一个使用 clang 实现的 C/C++ 代码文档生成器。 特点: 使用 clang 可靠解析大多数复杂的 C++ 项目 零配置 使用 markdown 做为文档格式 生成描述 API 的 XML 文档 使用简单格式用于文...

匿名
2013/02/14
1.4K
0
REST/HTTP 工具包--Spray

Spray 是一个开源的 REST/HTTP 工具包和底层网络 IO 包,基于 Scala 和 Akka 构建。轻量级、异步、非堵塞、基于 actor 模式、模块化和可测试是 spray 的特点。 示例代码: val responses: F...

匿名
2013/02/20
7K
0
Android3D应用与游戏开发框架--JQGL

JQGL 是一款针对Android设备上3D应用、游戏的开发框架。 核心功能是OpenGL-ES的使用框架,相对于大部分开发者而已,OpenGL是陌生的,没有专门研究无法进行相关的开发。 本框架针对于Android...

Jping
2013/02/21
1.6K
0
OpenConnect VPN 服务器--ocserv

ocserv 全称是 OpenConnect VPN Server。实现了 AnyConnect SSL VPN 协议,兼容 OpenConnection VPN 客户端。特点是体积小、安全和可配置。依赖标准协议如 TLS 1.2 和数据报文 TLS。...

匿名
2013/03/06
8.7K
0

没有更多内容

加载失败,请刷新页面

加载更多

数据库高频面试点,事务/乐观锁/悲观锁/CAS/MySQL存储引擎

事务的ACID特性是什么? 原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用; 一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读...

osc_45536bvu
29分钟前
16
0
大数据BI软件助力企业数字化转型

当下,「新基建」势头正盛,随着“新基建”成为热议话题,数字化也随之成为企业面临的新机遇和新挑战。新基建的核心就是数据,数据是数字经济和企业数字化转型的生产要素和发展动力。 再看看...

osc_0boqdoe2
30分钟前
0
0
凯旋创投来志刚:基因治疗新时代,大戏刚刚开始

  2017 年,全球第一个基因治疗方法 CAR-T 细胞药物 Kymriah 获得 FDA 上市批准,从此掀起了基因治疗的热潮。随着相关技术和政策的不断成熟,基因治疗市场也随之扩大。根据德勤发布的《引领...

osc_k3vwonkw
32分钟前
10
0
LightningChart.NET使用两个BarSeries创建简单的2D图表

本教程介绍了如何使用两个BarSeries创建简单的2D图表。 BarSeries将数据值表示为矩形条,并且可以用于以非常清晰的方式可视化数据之间的差异和方差。 在本教程中,BarSeries用于表示两年期间...

roffey
32分钟前
0
0
Mybatis trim 标签的 2 个妙用!

云栖号资讯:【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! mybatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼...

osc_x03qsedc
33分钟前
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部