就是写一个实例化一次的类
即把构造私有化,外部无法实例化他。通过调用他的静态方法,判断是否实例化了,未实例化则实例化并返回,已实例化则返回已实例化的。
一:
/**
* 基于双重检查锁定的单例模式
* @author zongzhimin
*
*/
public class SingleDog4{
/**
* 在错误示范2的基础上给instance加 volatile进行修饰
* volatile可以保证instance的可见性禁止上个错误示例的那种重排序
*/
private static volatile SingleDog4 instance = null;
private SingleDog4(){
}
public static SingleDog4 getInstance(){//双重检查防止多线程下出问题
if (null == instance){// 1
synchronized (SingleDog4.class){
if(null == instance) {
instance = new SingleDog4();//2
}
}
}
return instance;
}
public void say(){
System.out.println("Single all the way");
}
}
二:
/**
* 基于静态内部类的单列模式
* @author zongzhimin
*
*/
public class SingleDog6{
private SingleDog6(){
}
private static class InstanceHolder{
final static SingleDog6 instance = new SingleDog6();
}
public static SingleDog6 getInstance(){
return InstanceHolder.instance;
}
public void say(){
System.out.println("Single all the way");
}
}
性能不好:
/**
* 这个性能不好
* @author zongzhimin
*
*/
public class SingleDog{
private static SingleDog instance = null;
private SingleDog(){
}
public static SingleDog getInstance(){//这里每次获取实例都要先获取锁,性能不好
synchronized (SingleDog.class){
if (null == instance){
instance = new SingleDog();
}
return instance;
}
}
public void say(){
System.out.println("Single all the way");
}
}
错误示范1:
/**
* 错误示范1
* @author zongzhimin
*
*/
public class SingleDog2{
private static SingleDog2 instance = null;
private SingleDog2(){
}
/**
* 这里做了改进将静态快放在里面但是这是错误的!!!
* 多线程下A线程到1, B线程到2 -->(A判断instance==null、正好B线程执行完2实例化一次)-->(这时A线程会进入静态快再实例化一次。单例失败)
*
* @return
*/
public static SingleDog2 getInstance(){
if (null == instance){// 1
synchronized (SingleDog2.class){
instance = new SingleDog2();//2
}
}
return instance;
}
public void say(){
System.out.println("Single all the way");
}
}
错误示范2:
/**
* 错误示范2
* @author zongzhimin
*
*/
public class SingleDog3{
private static SingleDog3 instance = null;
private SingleDog3(){
}
/**
* 这里在错误示范的基础上做了改进增加一次进入静态快的判断!!!在块里再判断一次,避免错误示范2里面的再次实例化
* 但这依然是不正确的:
* 对于2操作: 可以分为 一:分配SingleDog3对象所需空间 二:初始化SingleDog3对象 三:将对象引用写入instance对象
* 由于重排序在临界区(静态快内的操作可以重排序)所以2操作可能是:一、三、二。
* 因此:
* 线程A进入静态快且进行一、三、二的 三这一步(还未走二实例化SingleDog3但是已先给instance变量赋地址)
* 而另一线程B进入1,发现instance不为null,然后return instance,此时线程A还未走完er,即SingleDog3还未实例化,程序出错
*
* @return
*/
public static SingleDog3 getInstance(){
if (null == instance){// 1
synchronized (SingleDog3.class){
if(null == instance) {
instance = new SingleDog3();//2
}
}
}
return instance;
}
public void say(){
System.out.println("Single all the way");
}
}