vlambda博客
学习文章列表

你知道单例模式几种写法吗?

我们知道Java中有23种设计模式,单例模式是其中的一种,你知道单例模式有几种写法吗?

1.饿汉式

public class Singleton_1 { private static final Singleton_1 INSTANCE = new Singleton_1();
private Singleton_1(){
} public Singleton_1 getInstance(){ return INSTANCE; }
}

优点:最简单的写法

缺点:无论使用或者不使用都会给它分配出一块内存出来

2.静态代码块方式

public class Singleton_2 { private static Singleton_2 Instance; static { Instance = new Singleton_2(); } private Singleton_2(){
} public static Singleton_2 getInstance(){ return Instance; }}

优点:简单快捷

缺点:浪费内存

3.懒汉式

public class Singleton_3 { private static Singleton_3 INSTANCE = null;
private Singleton_3() { }
public static Singleton_3 getInstance(){ if(INSTANCE==null){ return new Singleton_3(); } return INSTANCE; }}

优点:与饿汉式相比,在不用的情况下不会分配出内存了,只有在用的情况下,getInstance方法才会new出该对象

缺点:线程不安全,当第一个线程走到if时,第二个线程也走到if并且继续往下执行了,这样第一个线程也会继续往下走,会出现多个对象。

4.方法加锁

public class Singleton_4 { private static Singleton_4 INSTANCE = null;
private Singleton_4() { }
public static synchronized Singleton_4 getInstance(){ if(INSTANCE==null){ return new Singleton_4(); } return INSTANCE; }}

优点:线程安全

缺点:synchronized锁的范围太大了,因为只需要锁住return new Singleton_3();即可

5.方法内加锁并检查:

public class Singleton_5 { private static Singleton_5 instance = null;
private Singleton_5() {
}
public static Singleton_5 getInstance() {
if (instance == null) { synchronized (Singleton_5.class) { instance = new Singleton_5(); } } return instance; }}

优点:synchronized锁的范围小了

缺点:线程不完全,当两个线程同时到if是判断对象为null,两个线程同时去if里面抢锁,最终两个线程都会走完里面的代码,new出两个不同的对象。

6.方法内加锁双重检查

public class Singleton_6 { private volatile static Singleton_6 instance = null;
private Singleton_6(){
}
public static Singleton_6 getInstance(){ if(instance==null){ synchronized (Singleton_5.class){ if(instance==null){ instance = new Singleton_6(); } } } return instance; }
}

优点:线程安全,不会和上一种出现两个对象。

缺点:无

7.内部类的实现方式

public class Singleton_7 {
private Singleton_7(){
} private static class InstanceHolder{ static final Singleton_7 INSTANCE = new Singleton_7(); }
public static Singleton_7 getInstance(){ return InstanceHolder.INSTANCE; }}

优点:直接从内部类中获取对象,与第一种写法类似

缺点:与第一种写法相比,不会出现浪费内存的现象,内部类默认是不加载的,什么时候用到,什么时候加载。

8.枚举方式

public enum Singleton_8 { INSTANCE;
public Singleton_8 getInstance(){ return INSTANCE; }}

优点:最完美,不仅可以解决线程同步,还可以防止反序列化,枚举类没有构造方法

缺点:无