java设计模式——单例模式
一、什么情况下考虑使用“单例模式”?
??????????
??????? 单例模式使得一个类在任何情况下只有一个对象,通常当需要一个类来管理共享的资源(例如:线程池、注册表,缓存等)可以使用单例模式,因为我们需要保证这些全局资源只有一份。
??????? 单例模式的概念:
??????? 单例模式确保一个类只能有一个实例,而且为这个实例提供了一个全局访问点。
二、如何实现单例模式?
??????? ①将构造方法私有化
??????? ②通过一个private静态变量记录单例类的唯一实例。
??????? ③定义一个获取该实例静态方法。??????? 实现如下:
public class Singleton { private static Singleton singleton; private Singleton(){} //构造方法私有化 public static Singleton getInstance(){ if(singleton == null) singleton = new Singleton(); return singleton; }
?以上便实现了简单的单例模式,但是在多线程时可能会出现错误,所以需要对程序进行简单的修改如下:
?
对getInstance()方法添加同步锁:
?
public static synchronized Singleton getInstance() { if (singleton == null) singleton = new Singleton(); return singleton; }
?这样可以保证在其他线程进入getInstance()方法时需等待其他方法执行完getInstance()方法。
?
?
然而如果程序访问getInstance()方法的频率很高,这就会产生效率问题,我们可以采用单例中的饿汉模式,代码如下:
?
public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() { } //构造方法私有化 public static Singleton getInstance() { return singleton; } }
?这样就可以使得JVM在加载这个类时就创建这个类的唯一实例,那么即使在多线程中也不会出现问题。
?
?
??????? 然而如果程序中我们可能很多情况下不要调用这个类的话,加载马上就创建实例,又会造成很大的浪费,我们该怎么办呢?
?????? 可以使用“双重检查加锁”,在getInstance()中减少使用同步,只有在创建实例时添加同步锁,代码如下:
?
public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() { } //构造方法私有化 public static Singleton getInstance() { if(uniqueInstance == null){ synchronized (Singleton.class){ if(uniqueInstance == null) uniqueInstance = new Singleton(); } } return uniqueInstance; } }
?注意:uniqueInstance使用了volatile关键词修饰,volatile使得线程对缓存中数据的修改强制的写入主存,同时使得cpu中其他的线程缓存无效,需要从主存中重新读取(对多线程我也不太了解,以后慢慢学习吧)。
需要注意的是“双重检查加锁”不适用java 1.4及其以前版本。
?
在维基百科中也找到了关于延迟加载同时又避免加锁的另一个版本:
???? In software engineering, the Initialization on Demand Holder (design pattern) idiom is a lazy-loaded singleton. In all versions of Java, the idiom enables a safe, highly concurrent lazy initialization with good performance.
?
public class Singleton { private static class LazyHolder{ private static final Singleton uniqueInstance = new Singleton(); } private Singleton() { } //构造方法私有化 public static Singleton getInstance() { return LazyHolder.uniqueInstance; } }
?
?
?
?
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。