根据自己的经验总结一下,单例模式的几种写法:
1、在方法中创建单例,一进方法就锁定或直接把方法锁定。
/**
* @author RockeyLu
*
*/
package designpattern;
/**
* @author RockeyLu<br>
* 这样可以解决问题,但大家都知道同步会降低性能<br>
* 而且比你想象的还要严重一些的是:只有第一次执行此方法时,才真正需要同步,<br>
* 换句话说一旦实例化后,就不需要同步这个方法了,之后每次调用这个方法 ,同步都是一种累赘
*
*/
public class SingletonA {
private static SingletonA instance;
private SingletonA() {
}
public static synchronized SingletonA getInstance() {
if (instance == null) {
instance = new SingletonA();
}
return instance;
}
}
/**
* @author RockeyLu
*
*/
package designpattern;
/**
* @author RockeyLu<br>
* 这样可以解决问题,但大家都知道同步会降低性能<br>
* 而且比你想象的还要严重一些的是:只有第一次执行此方法时,才真正需要同步,<br>
* 换句话说一旦实例化后,就不需要同步这个方法了,之后每次调用这个方法 ,同步都是一种累赘
*/
public class SingletonB {
private static SingletonB instance;
private static Object lock = new Object();
private SingletonB() {
}
public static SingletonB getInstance() {
synchronized (lock) {
if (instance == null) {
instance = new SingletonB();
}
}
return instance;
}
}
大家都看到这种方法会拖垮性能,那要怎么做呢,请往下看。
2、直接在字段中进行赋值(“急切“的创建实例,而不用延迟实例化的做法)
/**
* @author RockeyLu
*
*/
package designpattern;
/**
* @author RockeyLu<br>
* 依赖JVM在加载这个类时马上创建此唯一的实例<br>
* JVM保证在任何线程访问instance静态变量之前,一定先创建实例
*
*/
public class SingletonC {
private static SingletonC instance = new SingletonC();
private SingletonC() {
}
public static SingletonC getInstance() {
return instance;
}
}
3、在方法中创建单例,如果实例为空时才锁定再创建实例,即延迟创建实现,用”双重检查加锁“,在getInstance()中减少使用同步。
/**
* @author RockeyLu
*
*/
package designpattern;
/**
* @author RockeyLu<br>
* 利用双重检查加锁,首先检查是否实例已经创建了,<br>
* 如果尚未创建,才进行同步。这样一来,只有第一次会同步,这正是我们想要的最优的方案。<br>
* 注意:JDK1.4或更低的版本中,使用"Volatile"会导致双重检查加锁的失效,所以此方案用于JDK1.5版本以上
*
*
*/
public class SingletonD {
private volatile static SingletonD instance;
private SingletonD() {
}
public static SingletonD getInstance() {
if (instance == null) {
synchronized (SingletonD.class) {
if (instance == null) {
instance = new SingletonD();
}
}
}
return instance;
}
}