单例模式
饿汉式
静态变量方式
public class Singleton1 {
private final static Singleton1 instance=new Singleton1();
private Singleton1() {}
public static Singleton1 getInstance() {
return instance;
}
}
静态代码块方式
public class Singleton2 {
private static Singleton2 instance;
static {
instance=new Singleton2();
}
private Singleton2() {}
public static Singleton2 getInstance() {
return instance;
}
}
懒汉式
线程不安全式
public class Singleton3 {
private static Singleton3 instance;
private Singleton3() {}
public static Singleton3 getInstance() {
if(instance==null) {
instance=new Singleton3();
}
return instance;
}
}
线程安全式
public class Singleton4 {
private static Singleton4 instance;
private Singleton4() {}
public synchronized static Singleton4 getInstance() {
if(instance==null) {
instance=new Singleton4();
}
return instance;
}
}
双重检查方式
public class Singleton5 {
private static volatile Singleton5 instance;
private Singleton5() {}
public static Singleton5 getInstance() {
if(instance==null) {
synchronized (Singleton5.class) {
if(instance==null) {
instance=new Singleton5();
}
}
}
return instance;
}
}
为什么需要双重检查?
加入有两个线程A、B都执行到了if(instance==null)
这个语句,而A线程先拿到了锁,生成了对象,如果A线程是否了锁,B线程此时拿到锁,如果不在执行一次判断if(instance==null)
的话,那么就又会生成一个实例,那么就不是严格的单例模式
静态内部类方式
public class Singleton6 {
private static class SingletonInstance{
private static final Singleton6 INSTANCE=new Singleton6();
}
private Singleton6() {}
public static Singleton6 getInstance() {
return SingletonInstance.INSTANCE;
}
}
外部类的加载不会导致内部类的加载,只有当内部类别使用时才会导致加载,并且类加载的时候JVM保证线程安全,所以利用这种方式即能保证线程安全又能保证懒加载
枚举方式
public enum Singleton7 {
INSTANCE;
public void method() {
System.out.println("method");
}
}
利用枚举的特性,得到的实例都是单例的。