设计模式之单例模式
单例模式的优点之为什么要使用单例模式
1.由于单例模式只生成一个实例,减小系统性能开销,当一个对象的产生需要多个资源时(读取配置文件、产生其他依赖)那么我们可以在应用启动时直接创建该对象实例,然后永久驻留内存。
2.单例模式可以在系统设置全局访问点,优化共享资源访问。例如可以设计一个单例类,负责所有数据表的映射处理。
五种单例模式的实现方式
饿汉式单例模式(线程安全,调用效率高,不能延时加载)
package singal;
/**
饿汉式单例 一上来就把对象加载了 可能会存在浪费内存的问题
**/
public class Hungry {
private Byte aByte1[]=new Byte[1024];
private Byte aByte2[]=new Byte[1024];
private Byte aByte3[]=new Byte[1024];
private Byte aByte4[]=new Byte[1024];
//构造函数私有化
private Hungry(){ }
private final static Hungry HUNGRY =new Hungry(); //类初始化时立即加载对象!
//方法没有同步所以调用效率高
public static Hungry getInstance(){
return HUNGRY;
}
}
懒汉式单例模式(调用效率不高、可以延时加载)
package singal;
//懒汉式
public class LazySingal {
private LazySingal(){
}
private static LazySingal LAZY_SINGAL; ////延迟加载,也称为懒加载 真正用的时候我们才加载
public static synchronized LazySingal getInstance(){ //如果不加同步的话会存在创建对象不唯一的情况
if (LAZY_SINGAL==null){
LAZY_SINGAL=new LazySingal();
}
return LAZY_SINGAL;
}
}
DCL懒汉式单例模式(volatile)(懒汉式以及双重检测锁式)
package singal;
import javax.sound.midi.Soundbank;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
懒汉式单例
**/
public class LazyMan {
private static Boolean XUAN =false; //自定义布尔常量防止反射创建新对象
//构造函数私有
private LazyMan(){
synchronized (LazyMan.class){
if (XUAN==false){
XUAN=true;
}else throw new RuntimeException("不要试图通过反射来破坏单例!");
}
}
private volatile static LazyMan lazyMan; //延迟加载,也称为懒加载 真正用的时候我们才加载
//双重检测的懒汉式单例 DCL懒汉式
public static LazyMan getInstance(){
if (lazyMan==null){
synchronized (LazyMan.class){
if (lazyMan==null){
lazyMan= new LazyMan();
/**
* 为什么要加volatile?
* 因为在创建对象的时候
* 1.分配内存空间
* 2.执行构造方法初始化对象
* 3.把这个对象指向内存空间
* 原本顺序为123 但是在内存中是完全有可能发生指令排序出现问题的现象的比如132 这不算错误但是对于线程来说就 * 是会出现问题
* 如果A线程执行132 B线程进来时原本还没完成构造的A内存空间被误判为非空
* 于是B线程直接走return lazyMan 但是这空间却是虚无的
*/
}
}
}
return lazyMan;
}
//测试多线程并发
/*public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}*/
//通过反射来破坏单例
public static void main(String[] args) throws Exception {
//拿到XUAN字段
Field xuan = LazyMan.class.getDeclaredField("XUAN");
//将private失效
xuan.setAccessible(true);
//懒汉式实例对象
//LazyMan instance = LazyMan.getInstance();
//获取空构造
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
//使private失效
declaredConstructor.setAccessible(true);
//构造实例对象
LazyMan newInstance = declaredConstructor.newInstance();
//set false就是为了能够再创建对象
xuan.set(newInstance,false);
LazyMan newInstance1 = declaredConstructor.newInstance();
//对象比较
System.out.
