2021-08-05

设计模式

一、单例模式

单例模式的特点:单例类只能有一个实例;单例类必须自己创建自己唯一的实例;单例类必须给所有其他对象提供这唯一实例

1、懒汉式

/**
 * 懒汉式单例模式,在第一次调用的时候实例化自己
 */
@Getter
@Setter
public class Singleton {
    private String name;
    private Singleton(){}
    private static Singleton single;

    /**
     * 静态工厂方法
     * 存在线程安全问题,线程不安全的
     * @return single
     */
    public static Singleton getInstance(){
        if(single==null){
            single = new Singleton();
        }
        return single;
    }

    /**
     * 同步方法 线程安全的 效率低
     * @return single
     */
    public static synchronized Singleton getInstanceSynchronized(){
        if(single==null){
            single = new Singleton();
        }
        return single;
    }

    /**
     * 双重校验锁定
     * @return single
     */
    public static Singleton getInstanceTwoCheck(){
        if (single==null){
            synchronized (Singleton.class){
                if (single==null){
                    single = new Singleton();
                }
            }
        }
        return single;
    }
    //静态类部类(推荐使用)
    public static class LazyHolder{
        private static final Singleton SINGLE = new Singleton();
    }
    public static final Singleton getInstanceLazyHolder(){
        return LazyHolder.SINGLE;
    }
}

2、饿汉式

/**
 * 饿汉式单例模式
 */
public class HungryHanStyle {

    //饿汉式单例类.在类初始化时,已经自行实例化,以后不再改变,所以天生是线程安全的
    private static final HungryHanStyle HAN_STYLE = new HungryHanStyle();
    private HungryHanStyle(){}
    public static HungryHanStyle getInstance(){
        return HAN_STYLE;
    }
}

3、登记式单例

/**
 * 登记式单例
 */
public class RegisteredSingleExample {
    //集合存放实例对象
    private static Map<String,RegisteredSingleExample> map = new HashMap<>();
    //保护的默认构造方法
    protected RegisteredSingleExample(){};
    //创建返回唯一实例的静态工厂
    public static RegisteredSingleExample getInstance(String name) throws ClassNotFoundException, IllegalAccessException, InstantiationException 
        if (name==null){
            name = RegisteredSingleExample.class.getName();
        }
    	//判断是否存在改实例对象,若不存在则创建
        if (map.get(name)==null){
            map.put(name, (RegisteredSingleExample) Class.forName(name).newInstance());
        }
        return map.get(name);
    }

    public  Map<String,RegisteredSingleExample> getMap(){
        return map;
    }
}


//继承RegisteredSingleExample;单例对象存入map集合,下次可直接调用,不需要从新实例化
public class Registered extends RegisteredSingleExample {

    public static Registered getInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        return (Registered) Registered.getInstance("com.zgq.entity.dto.Registered");//这里调用的是父类的方法,这里发生了向下转换
    }
}

4、测试

public class TestDemo {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {

        RegisteredSingleExample example1 = RegisteredSingleExample.getInstance(null);
        Registered registered = Registered.getInstance();
        System.out.println(example1+"   "+registered);
        RegisteredSingleExample re = new RegisteredSingleExample();
        Map<String, RegisteredSingleExample> map = re.getMap();
        System.out.println(map);

        ExecutorService es=new ThreadPoolExecutor
                (0,//核心线程池大小,只要有任务就会最少创建这么多线程来执行任务
                        200,//最大线程数
                        3000L, TimeUnit.SECONDS, //当线程数大于核心时,此为多于线程等待新任务的最长时间,超过时间便会死亡
                        new SynchronousQueue<>()//用来储存等待执行任务的线程
                );

        es.execute(new RunTest());
        Thread thread = new RunTest2();
        thread.start();
    }
}

class RunTest implements Runnable{
    @SneakyThrows
    @Override
    public void run() {
//        Singleton instance = Singleton.getInstanceTwoCheck();
//        HungryHanStyle instance = HungryHanStyle.getInstance();
        RegisteredSingleExample instance = RegisteredSingleExample.getInstance(null);
        System.out.println(instance);
    }
}

class RunTest2 extends Thread{
    @SneakyThrows
    public void run() {
//        Singleton instance = Singleton.getInstanceTwoCheck();
//        HungryHanStyle instance = HungryHanStyle.getInstance();
        RegisteredSingleExample instance = RegisteredSingleExample.getInstance(null);
        System.out.println(instance);
    }
}
上一篇:《设计模式:可复用面向对象软件的基础》之单例模式


下一篇:Java自学笔记:单例设计模式:饿汉式、懒汉式