java设计模式——单例模式(三)

容器单例模式

之前学习Structs2,Spring框架时,经常会听到单例,多例。虽然这与单例模式不太一样,但是都很类似。在程序运行的时候,就加载所有的实例,然后用的时候直接取出

看下面代码:

/**
 * @program: designModel
 * @description: 容器单例模式
 * @author: YuKai Fan
 * @create: 2018-12-11 14:59
 **/
public class ContaineSingleton {
    private ContaineSingleton() {}
    private static Map<String, Object> singletonMap = new HashMap<String, Object>();

    public  static void putInstance(String key, Object instance) {
        if (StringUtils.isNotBlank(key) && instance != null) {
            if (!singletonMap.containsKey(key)) {
                singletonMap.put(key, instance);
            }
        }
    }

    public static Object getInstance(String key) {
        return singletonMap.get(key);
    }
}

但是,这种方式在不考虑序列化与反射的情况下,依旧是不安全的。因为在多线程的环境下,还是会产生不同的实例,这需要结合场景来使用。

如果使用hashTable来保证线程安全的话,效率会很低,频繁去取实例都回家加同步锁。如果使用ConcurrentHashMap,由于被static修饰,相当于直接操作了 map,在这种场景下,也不是绝对的线程安全。

ThreadLocal环境下的"单例模式"

这种带引号的单例模式,并不是真正的单例模式。因为并不能保证整个应用只产生一个实例,只会保证整个应用线程唯一

/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2018-12-11 15:17
 **/
public class ThreadLocalInstance {
    private static final ThreadLocal<ThreadLocalInstance> threadLocalInstance = new ThreadLocal<ThreadLocalInstance>(){
        @Override
        protected ThreadLocalInstance initialValue() {
            return new ThreadLocalInstance();
        }
    };
    private ThreadLocalInstance() {}

    public static ThreadLocalInstance getInstance() {
        return threadLocalInstance.get();
    }

}
/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2018-12-04 14:11
 **/
public class T implements Runnable {
    public void run() {

        ThreadLocalInstance instance = ThreadLocalInstance.getInstance();
        System.out.println(Thread.currentThread().getName() + "" + instance);

    }
}
/**
 * @program: designModel
 * @description:
 * @author: YuKai Fan
 * @create: 2018-12-04 14:07
 **/
public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
//        LazySingleton lazySingleton = LazySingleton.getInstance();
        Thread t1 = new Thread(new T());
        Thread t2 = new Thread(new T());
        t1.start();
        t2.start();
        System.out.println("测试");
    }
}

输出结果:

产生的是不同的实例,但是ThreadLocal回味每个线程提供独立的变量副本,将每个线程的实例隔离。保证在多线程的情况下,会保证每个线程只能产生一个实例

单例模式源码分析

单例模式在jdk下的应用:

java.lang.Runtime下的getRuntime()方法,属于饿汉式

AWT下的Desktop类中的getDesktop()

猜你喜欢

转载自www.cnblogs.com/FanJava/p/10103511.html