容器單例和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

相關文章
相關標籤/搜索