一、懒汉式写法
1、速度较快,但线程不安全写法:
public class Singleton{
private static Singleton instance;
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
优点:
1)、属于lazy loading(延迟加载)型,在第一次需要的时候才创建
缺点:
1)、多线程会导致线程不安全,或者多线程会创建多个实例
2、线程安全模式写法:
懒汉方法锁模式:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉双重校验锁:
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
优点:
1)、实现了延迟加载,达到单例同步的效果
缺点:
1)、使用方法锁效率太低,会收到类中其他锁的使用
二、饿汉式写法
1、基于classloder机制
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
优点:
1)、通过类装载的时候进行实例,避免多线程同步问题。
缺点:
1)、不能确认类在何时实例化的,而且是有那个方法引起实例化,没有达到延迟实例化的效果。
2、通过静态内部类
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点:
1)、同上,使用classloder的机制保证初始实例化只有一个线程,但在classloader装载了Singleton类时,并没有实例化单例,只有在调用getInstance的时候才进行了实例化,这样保证了延迟实例化。
3、枚举法单例:
public enum Singleton {
/**
*定义一个枚举变量,代表了Singleton一个实例
*/
INSTANCE;
public void whateverMenthod();
}
优点:
1)、它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
存在问题:
1、如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。
2、如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。如果复原多个对象,那就会有多个单例类的实例。
解决方案:
public class Singleton implements java.io.Serializable {
public static Singleton INSTANCE = new Singleton();
protected Singleton() {}
private Object readResolve() {
return INSTANCE;
}
}