啥是单例?单例能干啥啊?小伙伴是不是跟我有一样的疑惑
你看懂了吗,说实话我有点点懵,可能脑子不太好用
又是一顿乱搜,明白一些了,单例就是,这个类只有个实例。
举个日常生活中的例子。
你在电脑上打开一个任务管理器,只能打开一个
还有计数器,只能有一个,不然你创建一个,他创建一个,你们记的数就不准确了
前言
单例模式是指内容中有且只会创建一个对象的设计模式,在程序中多次使用同一个对象,且作用相同,为了防止频繁的创建对象,单例模式让程序内存中创建一个对象,让所有的调用者都共享这个单例对象。单例模式的类型分为两种:懒汉式和饿汉式
饿汉式
//饿汉模式
public class Hungry{
/**
*构造器私有拒绝别人创建这个对象
*/
private Hungry(){}
private final static Hungry HUNGRY=new Hungry();
public static Hungry getInstance(){
retrun HUNGRY;
}
}
饿汉式会浪费空间,因为程序在启动的时候就创建好了对象,没有使用就会是的内存浪费
懒汉式
//懒汉式
public class lazySingle{
private LazySingle(){}
private static LazySingle lazySingle;
public static LazySingle getInstance(){
if(lazySingle==null){
lazySingle=new LazySingle();
}
return lazySingle;
}
}
但是这样会不会出现问题呢,当然在单线程的情况下是没有问题的,要是在多线程的情况下就会出现问题。就会创建很多个问题;下面就是如何解决问题
双重检查锁
//双重检查锁
public class LazySingle(){
private LazySingle(){}
private static LazySingle lazySingle;
//双重检查锁
public static LazySingle getInstance(){
if(lazySingle==null){
synchronized (LazySingle.class){
if(lazySingle==null){
lazySingle=new LazySingle();
}
}
}
return lazySingle;
}
}
双重检查锁,这样就可以在多线程的情况下保证数据的安全创建
volatile 防止指令重排
我们有了双重检查锁就完整了吗,会不会出现其他的问题呢,当然会有的,因为在new LazySingle()的时候,其实是有可能发生了指令重排
什么指令重排?//todo
//双重检查锁
public class LazySingle(){
private LazySingle(){}
private volatile static LazySingle lazySingle;
//双重检查锁
public static LazySingle getInstance(){
if(lazySingle==null){
synchronized (LazySingle.class){
if(lazySingle==null){
lazySingle=new LazySingle();
}
}
}
return lazySingle;
}
}
静态内部类
静态内部类不是很懂 //todo
public class Holder {
private Holder(){
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
3.破坏单例
无论是饿汉式和还是懒汉式都是可以被破坏的。利用反射进行去破坏
public static void main(String[] args) throws Exception {
//通过正常方式获得对象
LazySingle instance = LazySingle.getInstance();
Constructor<LazySingle> declaredConstructor = LazySingle.class.getDeclaredConstructor(null);
//可访问私有构造器
declaredConstructor.setAccessible(true);
//利用反射构造新对象
LazySingle lazySingle = declaredConstructor.newInstance();
System.out.println(instance.equals(lazySingle)); //false
}
以上就是利用反射强制访问类的私有构造器,去创建另一个对象
今天就到这里,开始干活
我又来搞设计模式了,说反射会破坏单例,解决方案呢就是利用枚举的方式去防止被破坏。讲了一堆的