饿汉式
public class Single1 {
private static Single1 singleOne = new Single1();
private Single1(){}
public static Single1 getSingleOne() {
return singleOne;
}
}
-
懒汉式
public class Single2 {
private static Single2 single2;
private Single2(){}
public static Single2 getSingle2() {
if (single2 == null) {
single2 = new Single2();
}
return single2;
}
}
解决了饿汉式的问题,但是在多线程环境下使用依然可能创建多个对象
懒汉式加锁
public class Single3 {
private static volatile Single3 single3;
private Single3(){}
public static synchronized Single3 getSingle3() {
if (single3 == null) {
single3 = new Single3();
}
return single3;
}
}
解决了懒汉式中线程不安全的问题,但是在方法中加锁退变成了单线程执行的模式
双重检查锁形式
public class Single4 {
private static volatile Single4 single4;
private Single4(){}
public static Single4 getSingle4() {
// 第一个判断是为了避免所有的线程都直接进入 同步代码块
if (single4 == null) {
synchronized (Single4.class) {
// 如果没有该判断,可能多个线程都进入第一个if块,虽然同步块只有一个线程可以执行,但是已经进入第一个if块的代码还是可以执行new 命令,
// 这样就不能实现单例
if (single4 == null) {
single4 = new Single4();
}
}
}
return single4;
}
}
解决懒汉式的问题,这种方式已经算是比较完美的了,只是不能防止反序列化的形式来创建对象
使用内部类的形式创建单例
public class Single6 {
private Single6() {
}
private static class InnerSingle6 {
private static Single6 single6 = new Single6();
}
public static Single6 getSingle6() {
return InnerSingle6.single6;
}
}
使用枚举的形式来创建单例
public class Single5 {
private Single5(){}
private enum Single5Enum {
INSTANCE;
private Single5 single5;
Single5Enum() {
this.single5 = new Single5();
}
}
public static Single5 getSingle5() {
return Single5Enum.INSTANCE.single5;
}
}
枚举是不能使用 new 关键字来创建对象的,所以可以防止使用反序列化的形式来创建对象
- 由于枚举中的对象在一开始就创建好了,所以在多线程环境下使用也是线程安全的