手把手教你学会单例模式(2)
什么是单例模式单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,线程中的单例模式常用来做数据源的动态切换)。本章节主要是讲,线程单例模式、枚举单例模式、容器单例模式以及序列化和反射破坏单例模式的处理。
·
单例模式
ThreadLocalSingleton 线程单例模式
上一节开始也介绍过有关线程内的单例,主要就是利用了线程副本threadlocal来保证线程内单例。因为是线程独享,所以就不会初始化多次了。不多说,上代码。
public class ThreadLocalSingleton {
// 下面是简化代码 不得不说java8开始代码看起来是舒服了 但是阅读成本就增加了
// private static final ThreadLocal<ThreadLocalSingleton> local = ThreadLocal.withInitial(ThreadLocalSingleton::new);
private static final ThreadLocal<ThreadLocalSingleton> local = new ThreadLocal<ThreadLocalSingleton>() {
@Override
protected ThreadLocalSingleton initialValue() {
return new ThreadLocalSingleton();
}
};
private ThreadLocalSingleton() {
}
public static ThreadLocalSingleton getInstance() {
return local.get();
}
}
容器式单例模式
spring中就利用了容器模式来管理bean,主要是通过创建一个map对象来存储class名称和对应的实例化对象的。
public class ContainerSingleton {
//创建map来存储数据,起名ioc主要是让大家联想到spring的ioc
private static final Map<String, Object> ioc = new ConcurrentHashMap<>();
private ContainerSingleton() {
}
public static Object getInstance(String className) {
//这个位置是一定要增加锁的
//有人会问到,我不是已经使用ConcurrentHashMap了吗,为什么还要加锁呢
//这是因为有人把ConcurrentHashMap的线程安全和单例搞混了
//在ConcurrentHashMap中put和set等方法是线程安全的,也就是说在操作map中数据的时候可以保证线程安全
//但是并不是说我们的getInstance就是线程安全的了,是我们本身的代码存在问题
//假如说我们写的单例只有这些代码的话ConcurrentHashMap是可以换成HashMap的
synchronized (ioc) {
if (!ioc.containsKey(className)) {
Object object = null;
try {
object = Class.forName(className).newInstance();
//将实例化的对象放入ioc中
ioc.put(className, object);
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
return ioc.get(className);
}
}
}
枚举式单例
听名字就知道我们使用枚举类来创建单例,单例存在着一些天然的优势,在java的实现机制上,enum属性值本身就为单例,并且底层对序列化和反射破坏单例的问题进行了相关优化,当然缺点就是稍微占用了些资源。
public enum EnumSingleton {
INSTANCE;
public EnumSingleton getInstance(){
return INSTANCE;
}
}
这个可能稍微难理解了些,给大家写个例子
public class User {
private User(){}
static enum SingletonEnum{
INSTANCE;
private User user;
private SingletonEnum(){
user=new User();
}
public User getInstnce(){
return user;
}
}
public static final User getInstance(){
return SingletonEnum.INSTANCE.getInstnce();
}
}
破坏单例模式的情况
反射破坏单例
还在整理
序列化破坏单例
还在整理
更多推荐
已为社区贡献3条内容
所有评论(0)