通过懒汉模式:
package com.zcj.singlepattern;
//使用饿汉模式
public class SingleOne {
private static final SingleOne instance =new SingleOne();
private SingleOne(){
}
public static SingleOne getInstance(){
return instance;
}
}
下面用测试程序,可以看到二次调用输出的结果是一样的,说明是同一个实例
package com.zcj.singlepattern;
public class SingleTest {
public static void main(String[] args) {
SingleOne singleOne =SingleOne.getInstance();
System.out.println(singleOne);
SingleOne singleOne2 =SingleOne.getInstance();
System.out.println(singleOne2);
}
}
结果
com.zcj.singlepattern.SingleOne@4f1d0d
com.zcj.singlepattern.SingleOne@4f1d0d
也可以使用懒汉模式,
package com.zcj.singlepattern;
public class SingleTwo {
private static SingleTwo instance;
private SingleTwo(){
}
public static SingleTwo getInstance(){
if(instance==null){
instance = new SingleTwo();
}
return instance;
}
}
测试的代码类似,但是这种方法存在一个问题就是多线程访问的时候不一定能保证只创建一个,解决办法如下
package com.zcj.singlepattern;
public class SingleTwo {
private static SingleTwo instance;
private SingleTwo(){
}
public synchronized static SingleTwo getInstance(){
if(instance==null){
instance = new SingleTwo();
}
return instance;
}
}
在方法体上增加一个synchronized同步关键字,这种方法仍然可以进一步的优化,使用同步代码快,双重判断
package com.zcj.singlepattern;
public class SingleTwo {
private static SingleTwo instance;
private SingleTwo(){
}
public static SingleTwo getInstance(){
if(instance==null){
synchronized (SingleTwo.class) {
if(instance==null){
instance = new SingleTwo();
}
}
}
return instance;
}
}
阅读过java并发的人员可能会发现这里仍然存在一个问题,因为存在指令冲排序的问题
分配内存
初始化
将引用指向这个地址
如果第二步和第三步发生重排序,就可能导致空错误,保险的做法是在instance上增加一个volatile关键字来防止指令的重排序