如何安全的发布对象?
定义
安全的发布对象: 在可变对象没有被构造完成之前不允许被其他线程所使用
饿汉模式发布对象
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
|
/**
* 饿汉模式
*/
public class SingletonExample2 {
/**
* 私有构造方法
*/
private SingletonExample2(){
}
/**
* 单例的对象
* 在初始化需要较多操作的时候会比较耗时,程序启动的时候有性能问题
* 如果不被使用可能会导致资源浪费
*/
private static SingletonExample2 instance = new SingletonExample2();
/**
* 静态的工厂方法获取单例对象
* @return
*/
public static SingletonExample2 getInstance(){
return instance;
}
}
|
按需加载初始化对象
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
|
/**
* 双重同步锁检测机制
* 单利模式,对象在第一次使用的时候创建
*/
public class SingletonExample5 {
/**
* 私有构造方法
*/
private SingletonExample5(){
}
/**
* 单例的对象
* 使用volatile关键字限制指令重排序,
*/
private volatile static SingletonExample5 instance = null;
/**
* 对象创建的过程
* 1. memory = allocate() 分配对象空间
* 2. newInstance() 初始化对象
* 3. instance = memory 设置instance指向刚分配的内存
* jvm 和cpu 优化发生了指令重排序, 对象创建 顺序变成 1 3 2,会导致未初始化完成的对象被外部使用.尤其是在初始化对象操作比较漫长的时候
* volatile关键字的作用就是保证对象创建过程是 1 2 3
* 静态的工厂方法获取单利对象
* @return
*/
public static SingletonExample5 getInstance(){
if (instance == null){
// 双重检测机制
synchronized(SingletonExample5.class){
if (instance == null){
instance = new SingletonExample5();
}
}
}
return instance;
}
}
|
使用枚举发布对象
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
|
/**
* 基于枚举实现的单例模式
* 线程安全的懒汉模式,只有被实际调用的时候才会被初始化,jvm 保证
*/
public class SingletonExample7 {
private SingletonExample7(){
}
public static SingletonExample7 getInstance(){
return Singleton.INSTANCE.getInstance();
}
private enum Singleton {
INSTANCE;
private SingletonExample7 singleton;
/**
* jvm 保证这个方法被调用一次,并且只有在实际调用的时候才被初始化
*/
Singleton() {
singleton = new SingletonExample7();
}
public SingletonExample7 getInstance() {
return singleton;
}
}
}
|