单例模式是每个程序员都很清楚的设计模式
这里先介绍三种,饿汉式单例,懒汉式单例,静态内部类,直接code,比较清晰~
饿汉式单例:
package shejimoshi;
//饿汉式单例
public class HungrySingle {
//可能会浪费空间
private byte[] data1 = new byte[2024*2024];
private byte[] data2 = new byte[2024*2024];
private byte[] data3 = new byte[2024*2024];
private byte[] data4 = new byte[2024*2024];
private HungrySingle(){
}
private final static HungrySingle HUNGRY_SINGLE = new HungrySingle();
public static HungrySingle getInstance() {
return HUNGRY_SINGLE;
}
}
懒汉式单例:
package shejimoshi;
//懒汉式单例
public class LazyMan {
private LazyMan() {
System.out.println(Thread.currentThread().getName() + "ok");
}
private volatile static LazyMan lazyMan;
//双重检测锁模式的 懒汉式单例 DCL 懒汉式
public static LazyMan getInstance() {
if(lazyMan == null) {
synchronized (LazyMan.class) {
if (lazyMan == null) {
lazyMan = new LazyMan(); //不是一个原子性操作
/*
* 1. 分布内存空间
* 2. 执行构造方法,初始化对象
* 3. 把整个对象指向整个空间
*
* 123执行顺序可能是132,可能有问题,
* */
}
}
}
return lazyMan;
}
//多线程并发
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
LazyMan.getInstance();
}).start();
}
}
}
使用静态内部类:
package shejimoshi;
//静态内部类
public class Holder {
private Holder() {
}
public static Holder getInstance() {
return InnerClass.HOLDER;
}
public static class InnerClass {
private static final Holder HOLDER = new Holder();
}
}
反射可以通过setAccessible = true,破坏单例模式的私有性,所以上述都是不安全的
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
LazyMan instance1 = LazyMan.getInstance();
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
//破坏构造器私有性
declaredConstructor.setAccessible(true);
LazyMan instance2 = declaredConstructor.newInstance();
System.out.println("instance1 = " + instance1);
System.out.println("instance2 = " + instance2);
}
解决方式后续补充~