-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSingleton2.java
More file actions
98 lines (85 loc) · 3.25 KB
/
Copy pathSingleton2.java
File metadata and controls
98 lines (85 loc) · 3.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package cn.singleton;
public class Singleton2 {
/*
* 1. 线程不安全. 这种写法lazy loading很明显,但是致命的是在多线程不能正常工作。
*/
private static Singleton2 instance;
private static Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
/*
* 2. 线程安全. 这种写法能够在多线程中很好的工作, 它也具备很好的lazy loading,
* 但是,效率很低 大多数情况下不需要同步
*/
private static Singleton2 instance2;
private static synchronized Singleton2 getInstance2() {
if (instance2 == null) {
instance2 = new Singleton2();
}
return instance2;
}
/*
* 3. 这种方式基于classloder机制避免了多线程的同步问题, 不过,instance在类装载时就实例化,
* 虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法,
* 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,
* 这时候初始化instance显然没有达到lazy loading的效果
*/
private static Singleton2 instance3;
static {
instance3 = new Singleton2();
}
public static Singleton2 getInstance3() {
return instance3;
}
/*
* 4 这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程
*/
private static class SingletonHolder {
private static final Singleton2 INSTANCE = new Singleton2();
}
public static final Singleton2 getInstance4() {
return SingletonHolder.INSTANCE;
}
/*
* 5.枚举单例 这种方式是Effective Java作者Josh Bloch 提倡的方式,
* 它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象; 详见SingletonEnum 中写法
*/
/*
* 6. 双重校验锁
* 一个定义为volatile的变量是说这变量可能会被意想不到地改变, 这样,编译器就不会去假设这个变量的值了
* 。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,
* 而不是使用保存在寄存器里的备份。
* 问题:
* 1.如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,
* 例如一些servlet容器对每个servlet使用完全不同的类装载器,
* 这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。
* 2.如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。
* 不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。
*/
private volatile static Singleton2 INSTANCE6;
public static Singleton2 getInstance6() {
if (INSTANCE6 == null) {
synchronized (Singleton2.class) {
if (INSTANCE6 == null) {
INSTANCE6 = new Singleton2();
}
}
}
return INSTANCE6;
}
/**
* 测试枚举方法
*
* @param args
*/
public static void main(String[] args) {
// 遍历枚举
for (SingletonEnum c : SingletonEnum.values()) {
System.out.println(c.sayHi());
}
SingletonEnum.INSTANCE.getInstance();
}
}