老大一直说要用这个来做面试题,让面试的人来写一个线程安全的单例模式,感觉自己还没掌握,把 Head first--Design Patterns 找了出来,以下大部分内容抄袭自这本书,略有增删改。
1. 全局变量的缺点:
必须在程序一开始就创建好对象,如果程序在这次的执行过程中又一直没用到它,就非常耗费资源。
2. 经典的单例模式实现:
public class Singleton {
//用一个静态变量来记录Singleton类的唯一实例
private static Singleton uniqueInstance;
private Singleton() {}
//注意这个方法也是静态的
public static Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
单例常被用来管理共享的资源,例如数据库连接、线程池、缓存、注册表。
单例模式确保一个类只有一个实例,并提供一个全局访问点。
这个模式的问题:在多线程时,并不能保证这个类只被实例化一次。
3. 处理多线程:
public class Singleton {
//用一个静态变量来记录Singleton类的唯一实例
private static Singleton uniqueInstance;
private Singleton() {}
//注意这个方法也是静态的
public static synchronized Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
通过增加synchronized关键字到getInstance()方法中,迫使每个线程在进入方法之前,要先等别的线程离开该方法。也就是说,不会有两个线程可以同时进入这个方法。
这种方法存在的问题:只有第一次执行此方法时,才真正需要同步。换句话说,一旦设置好uniqueInstance变量,就不再需要同步这个方法了。之后每次调用这个方法,同步都是一种浪费。
4.改善多线程
4.1 如果getInstance()的性能对应用程序不是很关键,就不用优化了
4.2 使用急切创建实例,而不用延迟实例化的做法
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return uniqueInstance;
}
}
标红的语句在静态初始化器(static initializer)中创建单例,这保证了线程安全。
利用这个做法,JVM在加载这个类时马上创建此唯一的单件实例。JVM保证任何线程访问uniqueInstance静态变量之前,一定先创建些实例。
4.3 用“双重检查加锁”,在getInstance()中减少使用同步
首先检查实例是否已经创建,如果尚未创建,才进行同步。这样一来,只有第一次会同步,这正是我们想要的。
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if(uniqueInstance == null) { //(1)
//只有第一次才彻底执行这里的代码
synchronized() {
//再检查一次
if(uniqueInstance == null)
uniqueInstance = new Singleton();
}
}
return uniqueInstance;
}
}
在最开始如果有1、2、3个线程走到了(1)处,假设1进入了同步块,2、3等待。1实例化后,2进入同步块,发现uniqueInstance已经不为空,跳出同步块。接着3进入,又跳出同步块。
volatile关键字确保:当uniqueInstance变量被初始化成Singleton实例时,多个线程正确地uniqueInstance变量。如果性能是你关心的重点,那么这个做法可以帮你大大地减少getInstance()的时间耗费。
分享到:
相关推荐
保证一个类只有一个实例,并提供一个访问它的全局访问点,使得系统中只有唯一的一个对象实例,具有线程安全,多线程测试通过。 1.打开日志并创建日志文件夹 默认为程序启动路径 2.清理日志文件下日志数量 默认保留90...
使用"懒汉模式"与"饿汉模式"实现c++的单例模式,并且确保了单例模式的第一次实例化的线程安全,以及程序结束时,单例对象的资源收回,以防内存资源的泄漏
C++11实现线程安全的单例代码和测试代码,包含singleton.h,main.cpp,希望帮助到大家。
c++单例模式, 需要boost中的function、bind、shared_ptr支持; 很好用; 下载中含简单的测试代码; 原帖:http://blog.csdn.net/CDScan/archive/2009/11/21/4848084.aspx
下面小编就为大家带来一篇老生常谈C++的单例模式与线程安全单例模式(懒汉/饿汉)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Java中懒汉单例设计模式线程安全测试,单例设计模式的测试
本资源描述了C++11 中多线程的创建,C++11中std命名空间中将boost库中的Thread加入,boost多线程从准标准变为标准,其中还介绍了C++ 多线程下的单例模式的使用,本文档为txt文档
深入浅出:讲解单例模式,多线程安全和并发访问问题.让你轻松应对面试
单例模式三种线程安全的表达方式,其中枚举方式的单例是最安全的
主要介绍了python实现线程安全的单例模式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
JVM监控实例数 windows监控 线程测试 单例模式下测试JVM实例是否一个
单例模式的实现机制,并发情况下的单例模式的存在问题及解决方法,无锁的线程安全单例模式
主要介绍了Java 单例模式线程安全问题的相关资料,希望通过本文大家能了解掌握单例模式中线程安全的使用方法,需要的朋友可以参考下
这是一个关于多线程下的单例模式优化代码。public class Singleton { private static Singleton instance; private Singleton (){ } public static Singleton getInstance(){ //对获取实例的方法进行同步 if...
单例模式的七种实现方法以及分析,可以作文大作业提交 1.前言 4 1.1 课题的研究背景 4 1.2 课题主要研究目标 4 2.相关技术简介 4 2.1Java简介 4 2.2IDEA简介 4 3. 单例模式的7种实现方式 5 3.1饿汉式(使用静态常量...
主要介绍了Java线程安全中的单例模式,需要的朋友可以参考下
Java多线程--解决单例模式中的懒汉式的线程安全问题
计算机后端-Java-Java核心基础-第20章 多线程 11. 线程安全的单例模式之懒汉式.avi