单例模式(Singleton Pattern)

单例模式使用场景很多:session,上下文,数据库连接池,全局配置文件等。

单例模式的写法也有很多种:

1.饿汉式 : 加载类的时候,就创建对象。线程安全。但有的时候不一定用得着,可能造成内存浪费。

package stu.design.singleton.hungry;

public class HungrySingleton {

    private static final HungrySingleton hungrySingleton = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return hungrySingleton;
    }
}
View Code

1.2 静态饿汉式:在类中的静态属性中创建类。

package stu.design.singleton.hungry;

public class HungryStaticSingleton {

    private static final HungryStaticSingleton hungrySingleton;

    static {
        hungrySingleton = new HungryStaticSingleton();
    }

    private HungryStaticSingleton() {
    }

    public static HungryStaticSingleton getInstance() {
        return hungrySingleton;
    }
}
View Code

2.懒汉式: 第一次调用getInstance()方法的时候再创建。 容易造成线程安全问题。

package stu.design.singleton.lazy;

public class LazySimpleSingleton {

    private static LazySimpleSingleton lazy = null;

    private LazySimpleSingleton() {
    }

    public synchronized static LazySimpleSingleton getInstance() {
        if (null == lazy) {
            lazy = new LazySimpleSingleton();
        }
        return lazy;
    }
}
View Code

2.2 双重检测懒汉式:懒汉式中,使用synchronized 锁加到方法上,影响性能。 可以加锁到执行代码间。

package stu.design.singleton.lazy;

public class LazyDoubleCheckSingleton {

    private volatile static LazyDoubleCheckSingleton lazy = null;

    private LazyDoubleCheckSingleton() {
    }

    public static LazyDoubleCheckSingleton getInstance() {
        if (null == lazy) {
            synchronized (LazyDoubleCheckSingleton.class) {
                if (null == lazy) {
                    lazy = new LazyDoubleCheckSingleton();
                }
            }
        }
        return lazy;
    }
}
View Code

2.3 内部静态类的单例模式: 内部静态类在类加载的时候,JVM底层实现了实例化。其可能会被序列化破坏,需实现 Serializable 的 readResolve()方法

package stu.design.singleton.lazy;

import java.io.Serializable;

// static inner class
public class LazyInnerClassSingleton implements Serializable {

    // 防止反射破坏单例模式
    private LazyInnerClassSingleton() {
        if (null != LazyHolder.lazy) {
            throw new RuntimeException("not allow many instance");
        }
    }

    public static final LazyInnerClassSingleton getInstance() {
        return LazyHolder.lazy;
    }

    private static class LazyHolder {
        private static final LazyInnerClassSingleton lazy = new LazyInnerClassSingleton();
    }

    // 防止序列化破坏单例模式
    private Object readResolve(){
        return LazyHolder.lazy;
    }
}
View Code

3.枚举实现: 枚举的优势在于JVM底层避免了枚举类型被反射,序列化破坏其单例性。

package stu.design.singleton.register;

public enum EnumSingleton {
    INSTANCE;

    // 实例化的对象
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}
View Code

3.2 容器实现: 容器中线程不安全,容器使用个的是每个线程作为主键。 所以是每个线程是安全,但线程间不是同一单例。

package stu.design.singleton.register;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ContainerSingleton {
    
    private ContainerSingleton() {
    }

    private static Map<String, Object> ioc = new ConcurrentHashMap<>();

    public static Object getBean(String className) {
        synchronized (ioc) {
            if (!ioc.containsKey(className)) {
                Object obj = null;
                try {
                    obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return obj;
            }
            return ioc.get(className);
        }
    }
}
View Code

4.伪线程安全实现:每个线程的单例是安全的,但线程与线程间的不是安全的。

package stu.design.singleton.threadlocal;

/**
 * 伪线程安全
 * 使用threadLocal,多数据源动态切换
 * data source route
 */
public class ThreadLocalSingleton {

    private static final ThreadLocal<ThreadLocalSingleton> threadLocalInstance = new ThreadLocal<ThreadLocalSingleton>() {
        @Override
        protected ThreadLocalSingleton initialValue() {
            return new ThreadLocalSingleton();
        }
    };

    public static ThreadLocalSingleton getInstance() {
        return threadLocalInstance.get();
    }
}
View Code

推荐使用枚举实现。

欢迎指正。

原文地址:https://www.cnblogs.com/Payne-SeediqBale/p/10958884.html