单例
单例
Java 单例写法
double-checked locking
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public final class Singleton {
private Singleton() { }
private static volatile Singleton INSTANCE = null;
public static Singleton getInstance() {
if(INSTANCE == null) { // t2
// 首次访问会同步,而之后的使用没有 synchronized
synchronized(Singleton.class) {
if (INSTANCE == null) { // t1
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
- 为何么要两次判断 null
- volatile 的作用
HashMap 版本(线程不安全)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 单例 — 单线程单例
这个单例严格意义上讲并不完全算是单例,它只能算在 单个线程
中的单例,也就是在同一个线程中的它是单例的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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();
}
}
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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");
}
}
public class T implements Runnable {
@Override
public void run() {
ThreadLocalInstance instance = ThreadLocalInstance.getInstance();
System.out.println(Thread.currentThread().getName()+" "+instance);
}
}
运行结果:
1
2
3
4
5
6
7
8
9
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
这个单例之算是个伪单例,只能在一个线程里面实现单例
Android 中的 ThreadLocal 单例
Android 中的 AnimationHandler
使用 ThreadLocal 单例
1
2
3
4
5
6
7
8
9
public class AnimationHandler {
public final static ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
public static AnimationHandler getInstance() {
if (sAnimatorHandler.get() == null) {
sAnimatorHandler.set(new AnimationHandler());
}
return sAnimatorHandler.get();
}
}
本文由作者按照 CC BY 4.0 进行授权