单例的7种设计思路

1:饿汉式:final类不允许被继承,static实例能利用jvm的<clinit>确保同步,缺点就是无法保证被ClassLoader加载的singleton04在什么时候使用,

这就意味着singleton04实例所开辟的堆内存空间会驻留更久的时间,这种情况对轻资源的类来说影响很小,如果是一个重资源的类则不妥。

public final class Singleton01 {
private static Singleton01 singleton01 = new Singleton01();
private Singleton01(){};
public static Singleton01 getInstance(){
return singleton01;
}
}

2:懒汉式:在使用的时候再创建,但是无法保证线程安全
public final class Singleton02 {
private static Singleton02 singleton02 = null;
private Singleton02(){};
public static Singleton02 getInstance(){
if(null == singleton02){
singleton02 = new Singleton02();
}
return singleton02;
}
}

3:懒汉式2:能确保懒加载和线程同步,但是性能地下
public final class Singleton03 {
private static Singleton03 singleton03 = null;
private Singleton03(){}
public static synchronized Singleton03 getInstance(){
if(null == singleton03){
singleton03 = new Singleton03();
}
return singleton03;
}
}

4:Double-Check:能确保懒加载和提供同步性能,但是有可能出现singleton04先于其他资源实例,导致其他线程出现空指针异常;
分析:
如果第一个线程进入该方法,没有任何问题,此时其他线程在运行到第一个null判断时,发现不为null,则直接返回,此时由于jvm指令重排序和
Happen-beore规则,conn,socket,singleton04这三者无法确保实例化顺序,有可能出现singleton04最先被实例化,而conn和socket未被
实例化,所以有可能出现空指针异常,可以使用volatile关键字来防止这种重排序。
public final class Singleton04 {
Connection conn;
Socket socket;
private static volatile Singleton04 singleton04 = null;
private Singleton04(){}
public static Singleton04 getInstance(){
if(null == singleton04){
synchronized (Singleton04.class){
if(null == singleton04){
singleton04 = new Singleton04();
}
}
}
return singleton04;
}
}

5:Holder方式,利用<clinit>()来保证高性能同步,防止指令重排序,同时又满足懒加载,good。
public final class Singleton05 {
private Singleton05(){}
private static class Holder{
private static Singleton05 singleton05 = new Singleton05();
}
public static Singleton05 getInstance(){
return Holder.singleton05;
}
}
6:
未完待续。。。
posted on 2020-08-13 23:23  曾经那个少年  阅读(182)  评论(0编辑  收藏  举报