单例模式
确保一个类只有一个实例,并提供一个全局访问点.
1.饿汉
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
public static Singleton getInstance() {
return uniqueInstance;
}
private Singleton() {
}
}
public class Singleton {
private static Singleton uniqueInstance;
static {
uniqueInstance = new Singleton();
}
public static Singleton getInstance() {
return uniqueInstance;
}
private Singleton() {
}
}
没有实现懒加载.
2.懒汉
public class Singleton {
private static Singleton uniqueInstance;
public static Singleton getInstance() {
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
private Singleton() {
}
}
线程不安全,在多线程的情况下可能会出现多个实例.
public class Singleton {
private static Singleton uniqueInstance;
public static synchronized Singleton getInstance() {
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
private Singleton() {
}
}
通过增加synchronized关键字到getInstance()方法中,使每个线程在进入这个方法之前要先等候别的线程离开这个方法,也就是说不会有两个线程同步进入这个方法.但同步会降低性能并且只有第一执行此方法时才需要同步,设置好uniqueInstance这个变量后就不需要再同步这个方法.
3.静态内部类
public class Singleton {
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
}
这种方式利用classloder的机制来保证初始化instance时只有一个线程,饿汉只要Singleton类被装载了,instance就会被实例化,没有达到lazy loading效果,而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有通过调用getInstance方法,才会装载SingletonHolder类,从而实例化instance。
4.双重检查加锁
public class Singleton {
private volatile static Singleton uniqueInstance;
public static Singleton getInstance() {
if(uniqueInstance == null){
synchronized(Singleton.class) {
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
private Singleton() {
}
}
关于volatile可参考:Java 理论与实践: 正确使用 Volatile 变量
5.枚举
public enum Singleton {
INSTANCE;
public void doSomething(){
}
}