1.定义
单例模式,顾名思义即只有一个单例,只在构造的时候生成唯一一个,不会重复生成,常见的有task,任务管理器等。此外,单例模式是面试常考的一个内容,面试官经常会要求我们进行手写,常用的有懒汉式、饿汉式、双重检索、静态内部类实现、枚举(很好有人使用)。
2.核心思维
将构造方法私有化
3.常见类型
1)懒汉式(线程安全和线程不安全)
思想:用的时候再初始化
public class Instance{
private static Instance instance;
private Instance(){}//私有构造方法
private static Instance getInstance(){
if(instance==null){
instance=new Instance();
}
return instance;
}
}
懒汉,就是懒得做,不逼到自己跟前的时候坚决不会做。在调用getInstance()方法的时候,检测instance为空,此时才会new一个Instance的实例。
利弊:这种方式可能会引起重复创建实例,造成线程不安全的情况。解决方法是在static后添加关键字synchronized,引入锁的机制,但是这样的话,性能会大大下降,每次创建实例都需要通过锁就行判断,所以两种各有利弊。
2.饿汉式
思想:开局便初始化
public class Instance{
private static Instance instance=new Instance();
private Instance(){}
private static Instance getInstance(){
return instance;
}
}
饿汉,就是饿的受不了了,已经到了饥不择食的地步,所以刚开始的时候,就直接把实例创建出来了,等到要用的时候,直接返回。
利弊:这种方法问题比较明显,还没有用到的时候,实例就已经创建了,会造成资源的浪费,如果程序没有用到这个实例的话,浪费问题尤为明显,所以不推荐这种方法。
3.双重锁判断机制(Double check lock)
思想:双重判断+引入锁
public class Instance{
private static Instance instance;
private Instance(){}
private static Instance getInstance(){
if(instance==null){
synchronized(Instance.class){//synchronized加锁
if(instance==null){
instance=new Instance();}
}
}
return instance;
}
}
我们对其进行了两次的空值判断,当第一次进行判断的时候,如果此时为空,此时我们会用synchronized将对象进行加锁,从而避免了多次创建实例。然后再进行空值判断,当创建好了后,锁就释放了,返回创建好的实例。
利弊:此种方法是在懒汉式的基础上进行了修改,提高了性能,可以保证对象的唯一性,避免了多次创建。不足的地方便是代码冗余,需要两次判断空值。
4.静态内部类
思想:静态域只会在Java虚拟机装载类的时候初始化一次,从而保证单例
public class Instance(
private static class GetInstance{
private static final Instance instance=new Instance();
}
private Instance(){}
private static Instance getInstance(){
return GetInstance.instance;
}
)
当我们调用getInstance()方法的时候,此时GetInstance得到初始化,包含在其内的静态域也会得到初始化,此时就会得到Instance的实例。由于静态域在虚拟机中只会在装载类的时候初始化一次,以此来保证单例的创建和其安全性。
5.枚举
public enum Instance {
instance;// 定义一个枚举的元素,代表一个实例
public void Operation() {
//方法
}
}
枚举很好的解决了以上的弊端,但是很少有人使用,毕竟自己维护的代码最好大多数人都能看懂==。
以上就是个人对单例模式的理解,如有错误,欢迎指正,谢谢!