饿汉式
// final 不允许被继承
public final class Singleton {
// 饿汉式,先new
private static Singleton singleton = new Singleton();
// 私有构造不允许外部 new
private Singleton(){
}
public static Singleton getInstance(){
return singleton;
}
}
饿汉式的问题是 instance 在被 ClassLoader加载后很长时间才能在使用,如果类中的资源是重资源,那么就必须使用懒汉式
懒汉式
// final 不允许被继承
public final class Singleton {
// 饿汉式,先new
private static Singleton singleton = null;
// 私有构造不允许外部 new
private Singleton(){
}
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
问题是多线程下不能保证实例的唯一性。
懒汉式+ 同步
// 但是 只允许一个 线程 访问这个方法 ,效率就会很低
// final 不允许被继承
public final class Singleton {
// 饿汉式,先new
private static Singleton singleton = null;
// 私有构造不允许外部 new
private Singleton(){
}
public static synchronized Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
Double-check
//
// final 不允许被继承
public final class Singleton {
// 饿汉式,先new
// 不加 volatile 可能出现空指针异常 ,可能JVM指令的重排序
private volatile static Singleton singleton = null;
// 私有构造不允许外部 new
private Singleton(){
}
// 双重校验,可以进入方法
public static Singleton getInstance(){
if (singleton == null){
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
Holder 实现静态的私有内部类
// final 不允许被继承
public final class Singleton {
// 私有构造不允许外部 new
private Singleton(){
}
private static class Holder{
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return Holder.instance;
}
}
Singleton 类中,初始化过程中并不会创建 Singleton 的实例 ,只有当 Holder 类被主动引用的时候则会创建
枚举方式
枚举的方式不允许被继承,同时是线程安全的 ,只能被实例化一次
推荐使用枚举的方式
饿汉式
public enum Singleton {
INSTANCE;
// 私有构造不允许外部 new
private Singleton(){
System.out.println("Instance will be init immediately");
}
//
public static Singleton getInstance(){
return INSTANCE;
}
}
// 懒加载
把枚举作为内部类进行懒加载
public class Singleton {
private Singleton(){
}
private enum EnumHolder{
INSTANCE;
private Singleton instance;
EnumHolder(){
this.instance = new Singleton();
}
private Singleton getInstance(){
return instance;
}
}
public static Singleton getInstance(){
return EnumHolder.INSTANCE.getInstance();
}
}