单例模式大致分这四种,其他的基本都是这四个衍生出来的
1.饿汉式模式
2.懒汉式模式
3.注册式模式
4.ThreadLocal单例
首先,先说明一下定义单例:
单例模式(Singleton pattern) 是指确保一个类在任何情况下,绝对只有一个实例,并提供一个全局访问点。常见的单例:ServletContext、ServletConfig、ApplicationContext
1.饿汉式模式写法
/***
* 优点:简单、线程安全
* 缺点:可能造成内存浪费
*
*/
写法一:
public class HungrySingleton {
private static final HungrySingleton instance=new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance() {
return instance;
}
}
写法二:
public class HungrySingleton {
private static final HungrySingleton instanc;
//静态块,可以很好的写其他逻辑功能
static {
instanc = new HungrySingleton();
}
private HungrySingleton() {
}
public static HungrySingleton getInstance() {
return instance;
}
}
2.懒汉式设计
/**
* FileName:LazySimpleSingleton
* author:gyf
* Date:2021/7/1014:24
* 单例模式懒汉式加载
* 优点:避免内存浪费
* 缺点:线程不安全(方法锁,线程安全,外部排队) 效率低下
*/
public class LazySimpleSingleton {
private static LazySimpleSingleton instance;
private LazySimpleSingleton(){}
public static synchronized LazySimpleSingleton getInstance() {
if (instance == null)
instance = new LazySimpleSingleton();
return instance;
}
}
/**
* FileName:LazySimpleSingleton
* author:gyf
* Date:2021/7/1014:24
* 单例模式懒汉式加载
* 优点:避免内存浪费
* 缺点:线程不安全(DCL 增加双重检查锁,线程安全,内部排队) 效率低下
*/
public class LazySimpleSingleton {
private static LazySimpleSingleton instance;
private LazySimpleSingleton(){}
public static LazySimpleSingleton getInstance() {
synchronized (LazySimpleSingleton.class) {
if (instance == null)
instance = new LazySimpleSingleton();
return instance;
}
}
}
以上,都能够被反射破坏。
3.注册设计
不光反射能破坏单例,序列化和反序列化也能破坏单例,原型模式的clone()也能破坏单例
(插一句话:不能用反射创建枚举对象)
3.1 Enum
/**
**
*优点:防止反射破坏,线程安全,提高性能,优雅
*缺点:浪费内存
*/
public enum EnumSingleton {
instance;
private Object data;
public Object getData(){return data;}
public void setData(Object data){this.data=data;}
public static EnumSingleton getInstance(){
return instance;
}
}
3.2Container 单例模式用 的最多的就是IOC 懒加载
public class ContainerSingleton {
private ContainerSingleton(){}
private static Map<String,Object> ioc=new ConcurrentHashMap<>();
public static Object getInstance(String classname) {
Object instance=null;
if(!ioc.containsKey(classname)){
try {
instance = Class.forName(classname).newInstance();
ioc.put(classname,instance);
}catch (Exception e){
e.printStackTrace();
}
return instance;
}else{
return ioc.get(classname);
}
}
}
4.ThreadLocal
public class ThreadLocalSingleton {
//spring 数据源动态切换
private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance =
initialValue() {return new ThreadLocalSingleton();};
private ThreadLocalSingleton(){}
public static ThreadLocalSingleton getInstance(){
return threadLocalInstance.get();
}
}
总结:
饿汉式:
Huangry :、StaticHuangry
优点:简单易读、线程安全 缺点:资源浪费
懒汉式:
LazySimple 、优点:避免浪费 缺点:线程不安全、sync 后性能低
LazyDCL 、优点:提高性能,线程安全 缺点:可读性差
LazyInnerClass 优点:线程安全、懒加载 缺点:反射破坏
(加锁后性能低)
注册式:
Enum : 优点:避免反射攻击、线程安全 缺点:资源浪费
Container; 优点 懒加载 ,线程安全 缺点:使用复杂
序列化破坏单例:重新readResolve()方法
原型破坏单例:重写clone 方法
ThreadLocal :用于数据源动态切换