【06期】单例模式有几种写法?
阅读本文大概需要 6 分钟。
“你知道茴香豆的‘茴’字有几种写法吗?”
JDK版本:oracle java 1.8.0_102
饱汉模式
基础的饱汉
// 饱汉
// UnThreadSafe
public class Singleton1 {
private static Singleton1 singleton = null;
private Singleton1() {
}
public static Singleton1 getInstance() {
if (singleton == null) {
singleton = new Singleton1();
}
return singleton;
}
}
饱汉 - 变种 1
// 饱汉
// ThreadSafe
public class Singleton1_1 {
private static Singleton1_1 singleton = null;
private Singleton1_1() {
}
public synchronized static Singleton1_1 getInstance() {
if (singleton == null) {
singleton = new Singleton1_1();
}
return singleton;
}
}
饱汉 - 变种 2
// 饱汉
// UnThreadSafe
public class Singleton1_2 {
private static Singleton1_2 singleton = null;
public int f1 = 1; // 触发部分初始化问题
public int f2 = 2;
private Singleton1_2() {
}
public static Singleton1_2 getInstance() {
// may get half object
if (singleton == null) {
synchronized (Singleton1_2.class) {
if (singleton == null) {
singleton = new Singleton1_2();
}
}
}
return singleton;
}
}
https://monkeysayhi.github.io/2016/11/29/volatile关键字的作用、原理/
饱汉 - 变种 3
// 饱汉
// ThreadSafe
public class Singleton1_3 {
private static volatile Singleton1_3 singleton = null;
public int f1 = 1; // 触发部分初始化问题
public int f2 = 2;
private Singleton1_3() {
}
public static Singleton1_3 getInstance() {
if (singleton == null) {
synchronized (Singleton1_3.class) {
// must be a complete instance
if (singleton == null) {
singleton = new Singleton1_3();
}
}
}
return singleton;
}
}
饿汉模式
// 饿汉
// ThreadSafe
public class Singleton2 {
private static final Singleton2 singleton = new Singleton2();
private Singleton2() {
}
public static Singleton2 getInstance() {
return singleton;
}
}
值得注意的时,单线程环境下,饿汉与饱汉在性能上没什么差别;但多线程环境下,由于饱汉需要加锁,饿汉的性能反而更优。
Holder模式
// Holder模式
// ThreadSafe
public class Singleton3 {
private static class SingletonHolder {
private static final Singleton3 singleton = new Singleton3();
private SingletonHolder() {
}
}
private Singleton3() {
}
/**
* 勘误:多写了个synchronized。。
public synchronized static Singleton3 getInstance() {
return SingletonHolder.singleton;
}
*/
public static Singleton3 getInstance() {
return SingletonHolder.singleton;
}
}
枚举模式
基础的枚举
// 枚举
// ThreadSafe
public enum Singleton4 {
SINGLETON;
}
丑陋但好用的语法糖
枚举型单例模式的本质
// 枚举
// ThreadSafe
public class Singleton4 extends Enum<Singleton4> {
...
public static final Singleton4 SINGLETON = new Singleton4();
...
}
用枚举实现一些trick
这一部分与单例没什么关系,可以跳过。如果选择阅读也请认清这样的事实:虽然枚举相当灵活,但如何恰当的使用枚举有一定难度。一个足够简单的典型例子是TimeUnit类,建议有时间耐心阅读。
// 枚举
// ThreadSafe
public enum Singleton4_1 {
SINGLETON("enum is the easiest singleton pattern, but not the most readable") {
public void testAbsMethod() {
print();
System.out.println("enum is ugly, but so flexible to make lots of trick");
}
};
private String comment = null;
Singleton4_1(String comment) {
this.comment = comment;
}
public void print() {
System.out.println("comment=" + comment);
}
abstract public void testAbsMethod();
public static Singleton4_1 getInstance() {
return SINGLETON;
}
}
总结
推荐阅读:
【03期】如何决定使用 HashMap 还是 TreeMap?
微信扫描二维码,关注我的公众号
朕已阅
评论