网站运维主要做些什么工作,做shopify网站,长沙官网seo服务,简述网页布局设计技术单例模式
作用#xff1a;单例模式的核心是保证一个类只有一个实例#xff0c;并且提供一个访问实例的全局访问点。
实现方式优缺点饿汉式线程安全#xff0c;调用效率高 #xff0c;但是不能延迟加载懒汉式线程安全#xff0c;调用效率不高#xff0c;能延迟加载双重检…单例模式
作用单例模式的核心是保证一个类只有一个实例并且提供一个访问实例的全局访问点。
实现方式优缺点饿汉式线程安全调用效率高 但是不能延迟加载懒汉式线程安全调用效率不高能延迟加载双重检测锁在懒汉式的基础上解决并发问题静态内部类线程安全资源利用率高可以延时加载枚举单例线程安全调用效率高但是不能延迟加载
饿汉式
在类加载的时候立即实例化对象实现的步骤是先私有化构造方法对外提供唯一的静态入口方法
public class SingletonInstance1 {private byte[] b1 new byte[1024*1024];private byte[] b2 new byte[1024*1024];private byte[] b3 new byte[1024*1024];// 声明此类型的变量并实例化当该类被加载的时候就完成了实例化并保存在了内存中private final static SingletonInstance1 instance new SingletonInstance1();// 私有化所有的构造方法,防止直接通过new关键字实例化private SingletonInstance1(){}// 对外提供一个获取实例的静态方法public static SingletonInstance1 getInstance(){return instance;}
}在类加载时直接创建对象可能会造成空间的浪费
–
懒汉式
public class SingletonInstance2 {// 声明此类型的变量,但没有实例化private static SingletonInstance2 instance null;// 私有化所有的构造方法,防止直接通过new关键字实例化private SingletonInstance2(){}// 对外提供一个获取实例的静态方法public static SingletonInstance2 getInstance(){if(instance null){// 当instance不为空的时候才实例化instance new SingletonInstance2();}return instance;}
}外部调用getInstance()方法时才会创建对象(判断对象是否存在)但是不能保证多线程并发的情况下的线程安全所以就出现了双重检测锁模式
–
双重检测锁模式
public class SingletonInstance3 {// 声明此类型的变量,但没有实例化,防止指令重排private volatile static SingletonInstance3 instance;// 私有化所有的构造方法,防止直接通过new关键字实例化private SingletonInstance3(){}// 对外提供一个获取实例的静态方法public static SingletonInstance3 getInstance(){if(instance null){synchronized (SingletonInstance3.class){if(instance null){// 当instance不为空的时候才实例化instance new SingletonInstance3();/*1.分配内存空间2.执行构造法法初始化对象3.把这个对象指向这个空间如果不加volatile 会执行重排序 1 3 2*/}}}return instance;}
}静态内部类
public class SingletonInstance4 {// 静态内部类public static class SingletonClassInstance{// 声明外部类型的静态常量public static final SingletonInstance4 instance new SingletonInstance4();}// 私有化构造方法private SingletonInstance4(){}// 对外提供的唯一获取实例的方法public static SingletonInstance4 getInstance(){return SingletonClassInstance.instance;}
}枚举
public enum EnumSingle {INSTANCE;public EnumSingle getInstance(){return INSTANCE;}
}–
如何保证线程安全
推荐使用 静态内部类 或者 双重检测锁 配合volatile使用
–
反射破坏单例模式
代码如下
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class LazyMan {private static boolean jiamibiaozhi false; // 加密标志位// 私有化所有的构造方法,防止直接通过new关键字实例化private LazyMan(){synchronized (LazyMan.class){if(!jiamibiaozhi){ // 防止反射破坏单例jiamibiaozhi true;}else {throw new RuntimeException(不能试图使用反射破坏异常);}}System.out.println(Thread.currentThread().getName() LazyMan);}// 声明此类型的变量,但没有实例化, volatile防止指令重排private volatile static LazyMan instance;// 对外提供一个获取实例的静态方法public static LazyMan getInstance(){if(instance null){synchronized (LazyMan.class){if(instance null){// 当instance不为空的时候才实例化instance new LazyMan();/*1.分配内存空间2.执行构造法法初始化对象3.把这个对象指向这个空间如果不加volatile 会执行重排序 1 3 2*/}}}return instance;}// 反射破环单列public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {// LazyMan lazyMan LazyMan.getInstance();ConstructorLazyMan declaredConstructor LazyMan.class.getDeclaredConstructor(null); // 获取空参构造器declaredConstructor.setAccessible(true); // 暴力反射设置权限无视私有构造器LazyMan lazyMan1 declaredConstructor.newInstance(); // 通过空参构造器创建对象LazyMan lazyMan2 declaredConstructor.newInstance();System.out.println(lazyMan1);System.out.println(lazyMan2);}
}反射不能破坏枚举见源码