容器单例模式
代码演示
- 创建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);
}
}
- 创建测试类
/**
* @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");
}
}
-
测试结果
测试结果.png - 注意
虽然返回是同一个对象,但是特殊场景存在问题。
第一个线程放入一个对象,第二个线程也放入一个对象,然后都调用返回方法,返回的都是第二个对象。此时返回的是同一个对象。
当第一个线程放入一个对象时,调用返回方法,返回第一个对象;然后第二个线程才放入第二个对象,调用返回方法,返回第二个对象。此时返回的是不同的对象。
使用时要特别注意!
ThreadLocal线程“单例”
代码演示
- 创建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();
}
}
- 创建测试类
/**
* @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");
}
}
-
测试结果
测试结果.png - 结论
这种方式,在单个线程中是同一个对象,对象为线程私有。
开源框架应用
- 饿汉式:Runtime
- 容器单例:Desktop.getDesktop()
网友评论