设计模式 单例模式
双重检查锁
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;
}
}