容器单例和ThreadLocal"单例"

容器单例

咱们先看代码吧java

public class ContainerSingleton {

    private ContainerSingleton(){

    }
    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可是HashTable每次存取都会加上同步锁,性能损耗比较严重。或者使用ConcurrentHashMap。安全

ThreadLocal “单例“

这个单例严格意义上讲并不彻底算是单例,它只能算在单个线程中的单例,也就是在同一个线程中的它是单例的。咱们直接看代码吧。bash

public class ThreadLocalInstance {
    private static final ThreadLocal<ThreadLocalInstance> threadLocalInstanceThreadLocal
             = new ThreadLocal<ThreadLocalInstance>(){
        @Override
        protected ThreadLocalInstance initialValue() {
            return new ThreadLocalInstance();
        }
    };
    private ThreadLocalInstance(){

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

}
复制代码

而后咱们写个测试类测试一下。ide

咱们定义一个线程T,在这个线程里面获取这个单例对象。函数

public class T implements Runnable {
    @Override
    public void run() {
        ThreadLocalInstance instance = ThreadLocalInstance.getInstance();
        System.out.println(Thread.currentThread().getName()+" "+instance);
    }
}
复制代码

而后是测试类包含主函数。性能

public class SingletonTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        System.out.println("main thread"+ThreadLocalInstance.getInstance());
        Thread t1 = new Thread(new T());
        Thread t2 = new Thread(new T());
        t1.start();
        t2.start();
        System.out.println("program end");
    }
复制代码

咱们再看一下运行结果。测试

main threadcom.design.pattern.creational.singleton.ThreadLocalInstance@12edcd21
main threadcom.design.pattern.creational.singleton.ThreadLocalInstance@12edcd21
main threadcom.design.pattern.creational.singleton.ThreadLocalInstance@12edcd21
main threadcom.design.pattern.creational.singleton.ThreadLocalInstance@12edcd21
main threadcom.design.pattern.creational.singleton.ThreadLocalInstance@12edcd21
main threadcom.design.pattern.creational.singleton.ThreadLocalInstance@12edcd21
program end
Thread-0  com.design.pattern.creational.singleton.ThreadLocalInstance@3ec28870
Thread-1  com.design.pattern.creational.singleton.ThreadLocalInstance@7a56389b
复制代码

从结果咱们能够看出这个单例之算是个伪单例,只能在一个线程里面实现单例。spa

相关文章
相关标签/搜索