单例模式
- 只有一个实例;
- 必须由自己创建自己的唯一实例;
- 必须提供一个公共方法供其他对象使用自己的实例。
饿汉式单例模式
饿汉式顾名思义,不管你需不需要,只要你引用了该类,就会创建对象的实例。
* 经典的饿汉式单例模式
* [@author](https://my.oschina.net/arthor) wushuaiping
* [@date](https://my.oschina.net/u/2504391) 2018/3/10 上午9:17
*/
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getSingleton(){
return singleton;
}
}
懒汉式单例模式
but .. 上述写法无法做到lazy load(延迟加载),lazy load意思就是我在需要的时候才去创建实例。于是我们可以使用如下写法:
/**
* 保证lazy load的单例模式,懒汉式单例
* @author wushuaiping
* @date 2018/3/10 上午9:17
*/
public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getSingleton(){
if (singleton == null){
singleton = new Singleton();
return singleton;
}
}
}
线程安全的懒汉单例模式
but.. 上述写法无法保证线程安全性,如果在单线程环境下,上述写法,就不会出现创建重复的对象的情况,但是如果在多线程情况下,有多条线程同时调用了getSingleton()方法,那么极有可能创建出多余且重复的对象。那么此时想到的解决方案是对代码块或者方法加入同步锁,保证线程安全,于是我们可以这样写
/**
* 保证lazy load并且保证线程安全的单例模式,懒汉式单例
* @author wushuaiping
* @date 2018/3/10 上午9:17
*/
public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static synchronized Singleton getSingleton(){
if (singleton == null){
singleton = new Singleton();
return singleton;
}
}
}
或
/**
* 保证lazy load并且保证线程安全的单例模式,懒汉式单例
* @author wushuaiping
* @date 2018/3/10 上午9:17
*/
public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getSingleton(){
synchronized(Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
return singleton;
}
}
即保证线程安全也保证效率的懒汉式单例
but.. 通过上述写法,我们虽然保证了线程安全,但是我们代码的效率却降低了,why? 因为我们使用了synchronized啊,当一个线程进入synchronized修饰的方法或者代码块后,其他线程必须在后面排队,导致了代码的效率的降低,于是我们可以使用Duoble-check来继续优化代码:
/**
* 保证lazy load并且保证线程安全还兼顾了效率的单例模式,懒汉式单例
* @author wushuaiping
* @date 2018/3/10 上午9:17
*/
public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getSingleton(){
if (singleton == null){
synchronized(Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
该方式为什么能保证效率呢?我们写懒汉式单例的原因是,我们不想要在JVM加载类的时候就创建对象,而是在我们需要该对象的时候才去创建对象,所以我们想到了懒汉式单例模式,而正是因为懒汉式单例模式的特性,通过Duoble-check,每个线程经过第一个if(singleton == null)
的时候,基本都会因为之前已经创建过了该对象,而直接返回,所以,该方式效率得到了保证。
实现单例的方式有很多种。我只是列出了几种常见的单例模式,当然最常见的还是枚举。如果各位有更好的单例模式请指教,本文只做个人笔记记录,欢迎各位看官批评。 O(∩_∩)O谢谢