一.概念
确保一个类只有一个实例,并提供一个全局访问点来获取该实例。
二.UML
三.三种单例模式
- 饿汉模式:在类加载的时候就实例化一个自己的对象。
package com.zzy.singleton;
/**
* 饿汉模式
* @author eason
*
*/
public class Singleton {
//JVM在静态初始块中创建对象
//保证了在任何线程访问singleton变量之前,一定先创建此实
//保证了线程安全
//static确保Singleton类只有一个实例
//保证了单例
private static Singleton singleton = new Singleton();
//private构造函数,只能在该类内部使用
private Singleton(){
}
public static Singleton getInstance() {
return singleton;
}
}
- 懒汉模式:在实例第一次被引用时才将自己实例化
package com.zzy.singleton;
/**
* 懒汉模式
* @author eason
*
*/
public class Singleton {
//static确保Singleton类只有一个实例
//保证了单例
private static Singleton singleton = null;
//private构造函数,只能在该类内部使用
private Singleton(){
}
//synchronized确保每个线程在进入getInstance方法前
//要先等到别的线程离开该方法
//也就是说,最极端的情况时也不会有两个线程同时进入该方法,不会 new Singleton()两次
//保证了线程安全
public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
- 双重检查模式:相比懒汉模式中的每次调用getInstance方法都需要同步,双重检查模式只有第一次调用getInstance方法才会进入此同步块
package com.zzy.singleton;
/**
* 双重检查模式
* @author eason
*
*/
public class Singleton {
//static确保Singleton类只有一个实例
//保证了单例
//volatile确保当singleton被初始化成Singleton实例时
//多个线程正确处理singleton变量
private volatile static Singleton singleton = null;
//private构造函数,只能在该类内部使用
private Singleton(){
}
public static Singleton getInstance() {
//如果实例不为空,进入同步区
if(singleton == null) {
//只有第一次调用getInstance方法才会进入此同步块
synchronized (Singleton.class) {
//为什么这里还要检查一次???因为可能多个线程同时进入上一个if判断里面
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
四.使用场景
系统只需要拥有一个的全局对象。比喻线程池,日志对象等等。
五.单例的演变