单例模式
饿汉式 可能会浪费空间
//饿汉式单例模式
public class Hungry {
//可能会浪费空间
private byte[] data1=new byte[1024];
private byte[] data2=new byte[1024];
private byte[] data3=new byte[1024];
private byte[] data4=new byte[1024];
public Hungry(){
}
private final static Hungry HUNGRY=new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
DCL懒汉式 用的时候再加载
单线程
多线程 加锁两次检测 DCL懒汉式 new LazyMan()不是原子性操作 三步操作 指令重排 ==>加volatile关键字
ifif synchronized
//懒汉式单例模式
public class Lazy {
private static boolean key=false; //加密关键字
private Lazy(){
synchronized (Lazy.class){
if(key==false)
{
key=true;
}else
{
throw new RuntimeException("不要使用反射破坏异常");
}
}
}
private static volatile Lazy LAZY;
public static Lazy getInstance(){
//加锁 双重检测模式的 懒汉式单例 DCL懒汉式 原子性操作
if(LAZY==null)
{
synchronized (Lazy.class){
if(LAZY==null){
LAZY=new Lazy(); //不是原子性操作
/*
* 1. 分配内存空间
* 2. 执行构造方法初始化对象
* 3. 把这个对象指向这个空间
*
* 正确:123
* 错误:132 如果另一条线程B,在第三步时判断为非空 此时没有完成构建 空间中是虚无的 +volatile
* */
}
}
}
return LAZY;
}
/* //单线程下可以使用,但是多线程下不行
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(()->{
Lazy.getInstance();
}).start();
}
}*/
//反射可以破坏这种单例==>解决
/*
* */
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Lazy instance = Lazy.getInstance();
//Lazy instance2 = Lazy.getInstance();
Constructor<Lazy> declaredConstructors = Lazy.class.getDeclaredConstructor();
//破坏加密关键字
Field key = Lazy.class.getDeclaredField("key");
key.setAccessible(true);
key.set(instance,false);
declaredConstructors.setAccessible(true); //无视私有构造器
//Lazy instance = declaredConstructors.newInstance();
Lazy instance2 = declaredConstructors.newInstance();
System.out.println(instance.hashCode());
System.out.println(instance2.hashCode());
}
}
/*
并发情况下出现问题
Thread-1 ok
Thread-5 ok
Thread-4 ok
Thread-3 ok
Thread-0 ok
Thread-2 ok*/
静态内部类
//静态内部类 不安全
public class Holder {
public Holder() {
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER=new Holder();
}
}
枚举类
//enum 枚举 本身也是一个class 只不过继承了枚举的类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
class test{
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
EnumSingle instance = EnumSingle.INSTANCE;
// EnumSingle instance2 = EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
EnumSingle instance2 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance2);
}
}
/*
通过jad.exe反编译发现没有无参的构造方法,只有有参构造方法
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
at com.ji.demo03.test.main(EnumSingle.java:19)
*/