JUC并发编程—单例模式

单例模式

饿汉式

package com.zkw.single;

// 饿汉式单例
public class Hungry {
    
    

    // 可能会浪费资源
    private byte[] data1 = new byte[1024*1024];
    private byte[] data2 = new byte[1024*1024];
    private byte[] data3 = new byte[1024*1024];
    private byte[] data4 = new byte[1024*1024];

    private Hungry(){
    
    

    }

    private final static Hungry HUNGRY = new Hungry();

    public static Hungry getInstance(){
    
    
        return HUNGRY;
    }
}

懒汉式 DCL

多线程下单例不唯一

package com.zkw.single;

//懒汉式单例
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();//不是一个原子性操作
                }
            }
        }
        return lazyMan;
    }
    /**
     * lazyMan = new LazyMan()的三步
     * 1、分配内存空间
     * 2、执行方法,初始化对象
     * 3、把这个对象指向这个空间
     *
     * 正常,我们的期望执行顺序123
     * 在指令重排的时候
     *可能会把这三步变成132
     * 当成132的时候,而且在多线程的情况下,线程A为132
     * 则线程B直接return了,但是此时LazyMan还没有完成构造
     *
     * 解决方法: private  static LazyMan lazyMan;
     * 加上Volatile就可以了 private volatile static LazyMan lazyMan;
     */

    // 多线程并发
    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            new Thread(()->{
                LazyMan.getInstance();
            }).start();
        }
    }
}
package com.zkw.single;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class LazyMan2 {
    private static boolean flag = false;
    private LazyMan2(){
        synchronized (LazyMan2.class){
            if (flag == false){
                flag = true;
            } else {
                throw new RuntimeException("不要试图用反射破坏异常");
            }
        }
    }

    private volatile static LazyMan2 lazyMan2;

    //双重检测锁模式 懒汉式单例 DCL懒汉式
    public static LazyMan2 Instance(){
        //加锁
        if (lazyMan2 == null){
            synchronized (LazyMan.class){
                if(lazyMan2==null){
                    lazyMan2 = new LazyMan2();//不是一个原子性操作
                }
            }
        }
        return lazyMan2;
    }

    //使用反射破坏单例模式
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {

        Field flag1 = LazyMan2.class.getDeclaredField("flag");
        flag1.setAccessible(true);

        Constructor<LazyMan2> declaredConstructor = LazyMan2.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        LazyMan2 lazyMan21 = declaredConstructor.newInstance();

        flag1.set(lazyMan21,false);

        LazyMan2 lazyMan2 = declaredConstructor.newInstance();

        System.out.println(lazyMan21);
        System.out.println(lazyMan2);
    }
}

枚举

枚举当中没有无参构造,只有两个参数的有参构造

package com.zkw.single;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

//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;
        Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
        declaredConstructor.setAccessible(true);
        EnumSingle instance1 = declaredConstructor.newInstance();

        System.out.println(instance);
        System.out.println(instance1);
    }
}

おすすめ

転載: blog.csdn.net/fgets__/article/details/120781449