设计模式:单例模式(4)

2019-07-24  本文已影响0人  谁家的猪

容器单例模式

代码演示

  1. 创建ContainerSingleton类
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lijiayin
 */
public class ContainerSingleton {
    private ContainerSingleton() {
        
    }
    private static Map<String, Object> singletonMap = new HashMap<>();
    
    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);
    }
}
  1. 创建测试类
/**
 * @author lijiayin
 */
public class ContainerTest {

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            ContainerSingleton.putInstance("object", new Object());
            Object instance = ContainerSingleton.getInstance("object");
            System.out.println(Thread.currentThread().getName() + ":" + instance);
        });
        Thread t2 = new Thread(() -> {
            ContainerSingleton.putInstance("object", new Object());
            Object instance = ContainerSingleton.getInstance("object");
            System.out.println(Thread.currentThread().getName() + ":" + instance);
        });
        t1.start();
        t2.start();
        System.out.println("program end");
    }
}
  1. 测试结果


    测试结果.png
  2. 注意
    虽然返回是同一个对象,但是特殊场景存在问题。
    第一个线程放入一个对象,第二个线程也放入一个对象,然后都调用返回方法,返回的都是第二个对象。此时返回的是同一个对象。
    当第一个线程放入一个对象时,调用返回方法,返回第一个对象;然后第二个线程才放入第二个对象,调用返回方法,返回第二个对象。此时返回的是不同的对象。
    使用时要特别注意!

ThreadLocal线程“单例”

代码演示

  1. 创建ThreadLocalSingleton类
/**
 * @author lijiayin
 */
public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> threadLocalSingleton
            = ThreadLocal.withInitial(ThreadLocalSingleton::new);
    private ThreadLocalSingleton(){
        
    }
    public static ThreadLocalSingleton getInstance(){
        return threadLocalSingleton.get();
    }
}
  1. 创建测试类
/**
 * @author lijiayin
 */
public class ThreadLocalTest {

    public static void main(String[] args) {
        System.out.println("main:" + ThreadLocalSingleton.getInstance());
        System.out.println("main:" + ThreadLocalSingleton.getInstance());
        System.out.println("main:" + ThreadLocalSingleton.getInstance());
        System.out.println("main:" + ThreadLocalSingleton.getInstance());
        Thread t1 = new Thread(() -> {
            ThreadLocalSingleton instance = ThreadLocalSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + ":" + instance);
        });
        Thread t2 = new Thread(() -> {
            ThreadLocalSingleton instance = ThreadLocalSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + ":" + instance);
        });
        t1.start();
        t2.start();
        System.out.println("program end");
    }
}
  1. 测试结果


    测试结果.png
  2. 结论
    这种方式,在单个线程中是同一个对象,对象为线程私有。

开源框架应用

  1. 饿汉式:Runtime
  2. 容器单例:Desktop.getDesktop()
上一篇 下一篇

猜你喜欢

热点阅读