单例模式
- 单例模式英文名
Singleton pattern - 单例模式的定义
保证一个类有且仅有一个实例,并提供一个访问它的全局访问点。 - 单例模式的特点
3.1该单例类有且仅有一个实例对象;
3.2该单例类对象必须由单例类自行创建;
3.3该单例类对外提供一个访问该单例类实例对象的全局方法; - 单例模式的结构
- 单例模式的实现
5.1. 饿汉模式(线程安全、提前占用资源)
public class Singleton
{
private static Singleton singleton = new Singleton();
/**
* 私有构造器
*/
private Singleton() {}
/**
* 获取单例的实例对象
* @return singleton 单例对象
*/
public static Singleton getInstance()
{
return singleton;
}
}
5.2. 常量模式(线程安全、提前占用资源)
public class Singleton
{
public static Singleton singleton = new Singleton();
/**
* 私有构造器
*/
private Singleton() {}
}
5.3. 懒汉模式(线程不安全、第一次加载慢)
public class Singleton
{
private static Singleton singleton;
/**
* 私有构造器
*/
private Singleton() {}
/**
* 获取单里的实例对象
* @return singleton 单例对象
*/
public static Singleton getInstance()
{
if(null == singleton)
{
singleton = new Singleton();
}
return singleton;
}
}
5.4. 同步懒汉模式(线程安全、第一次加载慢、每次都有同步开销)
public class Singleton
{
private static Singleton singleton;
/**
* 私有构造器
*/
private Singleton() {}
/**
* 获取单里的实例对象
* @return singleton 单例对象
*/
public static synchronized Singleton getInstance()
{
if(null == singleton)
{
singleton = new Singleton();
}
return singleton;
}
}
5.5. 双重检查锁DCL模式(线程安全、第一次加载慢、效率高)
public class Singleton
{
private static Singleton singleton;
/**
* 私有构造器
*/
private Singleton() {}
/**
* 获取单里的实例对象
* @return singleton 单例对象
*/
public static Singleton getInstance()
{
if(null == singleton)
{
synchronized (Singleton.class)
{
if(null == singleton)
{
singleton = new Singleton();
}
}
}
return singleton;
}
}
5.6. 静态内部类模式(线程安全、提前占用资源)
public class Singleton
{
/**
* 私有构造器
*/
private Singleton() {}
private static class InnerClassSingleton
{
private static final Singleton singleton = new Singleton();
}
/**
* 获取单里的实例对象
* @return singleton 单例对象
*/
public static Singleton getInstance()
{
return InnerClassSingleton.singleton;
}
}
5.7. 枚举单例模式(线程安全、实现简单、内存开销大、抗反射和反序列化攻击)
public enum Singleton
{
INSTANCE;
public Singleton getInstance()
{
return INSTANCE;
}
}
5.8. 容器单例模式(方便管理单例)
import java.util.HashMap;
public class Singleton
{
private static HashMap<String,Object> MAP = new HashMap<String,Object>();
/**
* 私有够着器
*/
private Singleton() {}
/**
* 注册实例,并绑定key
* @param key
* @param instance
*/
public static void registerService(String key,Object instance)
{
if(!MAP.containsKey(key))
{
MAP.put(key, instance);
}
}
/**
* 根据key获取对应的实例
* @param key
* @return
*/
public static Object getInstance(String key)
{
return MAP.get(key);
}
}
5.9. 防止反射破坏单例(线程安全、抗反序列化攻击)
public class Singleton
{
private static Singleton singleton;
private static boolean FLAG = false;
/**
* 私有够着器,并预防反序列化攻击
*/
private Singleton()
{
if(!FLAG)
{
FLAG = true;
}
else
{
throw new RuntimeException("请勿破坏单例");
}
}
/**
* 获取单例的实例对象
* @return singleton 单例对象
*/
public static Singleton getInstance()
{
if(null == singleton)
{
synchronized (Singleton.class)
{
if(null == singleton)
{
singleton = new Singleton();
}
}
}
return singleton;
}
}
5.10. 防止序列化和反序列化破坏单例(线程安全、抗反射和反序列化)
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* 严谨的高效的单例写法
*/
public class Singleton implements Serializable
{
/**
* 序列化ID
*/
private static final long serialVersionUID = 1L;
/**
* 实例化次数判定标志,用于反序列化攻击
*/
private static boolean flag = false;
/**
* 闭合构造器,并仅允许一次实例化,否则报错
*/
private Singleton ()
{
if(!flag)
{
flag = true;
}
else
{
throw new RuntimeException("请勿破坏单例");
}
}
/**
* 单例内联对象
* @author Administrator
*
*/
private static class InnerClassSingleton
{
private static final Singleton singleton = new Singleton();
}
/**
* 单例实例化方法
* @return
*/
public static Singleton getInstance()
{
return InnerClassSingleton.singleton;
}
/**
* 反序列化过程中执行 readResolve方法时返回 单例 对象
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException
{
return InnerClassSingleton.singleton;
}
}
- 单例模式的应用
6.1.1. 资源共享
6.1.2. Windows的Task Manager(任务管理器)
6.1.3. Windows的Recycle Bin(回收站)
6.1.4. 网站的计数器
6.1.5. 应用程序的日志应用
6.1.6. Web应用的配置对象的读取
6.1.7. 数据库连接池的设计一般也是采用单例模式
6.1.8. 多线程的线程池的设计一般也是采用单例模式
6.1.9. 操作系统的文件系统 - 单例模式的衍生
有限的多例模式等