设计模式 单例模式

双重检查锁

package com.fh.design_mode.singleton.double_check_lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/**
 * 双重检查锁
 */
public class SingletonTest {

    public static void main(String[] args) {
        for (int i = 1; i <= 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "例对象=" + Singleton.getInstance());
            }, "线程" + i).start();
        }
    }
}

class Singleton {
    private static volatile Singleton instance = null;//volatile 禁止重排序

    private Singleton() {
    }

    @SneakyThrows
    public static Singleton getInstance() {
        if (instance == null) {//效率
            synchronized (Singleton.class) {
                System.out.println("【debug】" + Thread.currentThread().getName() + "获得对象锁");
                TimeUnit.SECONDS.sleep(2);
                if (instance == null) {//对象是否为空
                    /*
                    ①分配栈空间=》②分配堆内存=》③栈指针指向堆内存
                    因为重排序优化的存在
                    线程A①③栈指针指向堆内存,实例分配内存后就不是null。
                    线程B进入判断instance!=null,直接返回A线程创建的不完整的实例。
                    */
                    instance = new Singleton();
                }
                System.out.println("【debug】" + Thread.currentThread().getName() + "释放对象锁。。。");
            }
        }
        return instance;
    }
}

静态内部类

package com.fh.design_mode.singleton.static_inner_class;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/**
 * 静态内部类
 */
public class SingletonTest {

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                Singleton.SingletonHolder a = new Singleton.SingletonHolder();

                System.out.println(Singleton.getInstance());
            }).start();
        }
    }
}

class Singleton {

    private Singleton() {

    }

    static class SingletonHolder {
        //虚拟机会保证一个类的 <clinit>() 方法在多线程环境中能被正确的加锁、同步。
        private static Singleton INSTANCE = new Singleton();
    }

    @SneakyThrows
    public static Singleton getInstance() {
        TimeUnit.SECONDS.sleep(3);
        return SingletonHolder.INSTANCE;
    }
}

饿汉式

package com.fh.design_mode.singleton.hungry_lock;

import lombok.SneakyThrows;

import java.util.concurrent.TimeUnit;

/*
 *饿汉式
 * */
public class SingletonTest {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(Sinleton.getInstance());
            }).start();
        }
    }
}

class Sinleton {

    private static final Sinleton instance = new Sinleton();

    private Sinleton() {
    }

    @SneakyThrows
    public static Sinleton getInstance() {
        TimeUnit.SECONDS.sleep(2);
        return instance;
    }
}

应用场景

spring Bean

Spring Bean采用了双重校验锁以及ConcurrentHashMap作为容器实现了单例设计,生成的Bean在容器中有且仅有一个,也保证了在创建过程中内存有且仅有一个对象。并且通过三级缓存解决循环依赖的问题。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
        protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
                                  @Nullable final Object[] args, boolean typeCheckOnly) 
                                  throws BeansException {
            // Eagerly check singleton cache for manually registered singletons.
            Object sharedInstance = getSingleton(beanName);
        }
}
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null && allowEarlyReference) {
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            singletonObject = singletonFactory.getObject();
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
            return singletonObject;
        }
}
posted @ 2024-07-31 18:18  干饭达人GoodLucy  阅读(26)  评论(0)    收藏  举报