设计模式(java)1——单例模式

如果要保证系统里一个类最多只能存在一个实例时,我们就需要单例模式。例如:缓存池,数据库连接池,线程池,一些应用服务实例等。

1、懒汉模式——实现懒加载但线程不安全

package singleton;

//懒汉模式(线程不安全)

public class Singleton1 {
    private static Singleton1 instance;

    private Singleton1() {
    }

    public static Singleton1 getInstance() {
        if (instance == null) {
            instance = new Singleton1();
        }
        return instance;
    }
}

2、懒汉模式——实现懒加载,线程安全但效率低

public class Singleton2 {
    private static Singleton2 instance;

    private Singleton2() {
    }

    public static synchronized Singleton2 getInstance() {
        if (instance == null) {
            instance = new Singleton2();
        }
        return instance;
    }
}

效率低。锁住整个方法,上述代码中的一次锁住了一个方法, 这个粒度有点大。只需锁住new 语句。

3、双重校验锁。实现懒加载,线程安全,且效率较第二种高(推荐掌握)

public class Singleton7 {
    private volatile static Singleton7 singleton;

    private Singleton7() {
    }

    public static Singleton7 getInstance() {
        if (singleton == null) {
            synchronized (Singleton7.class) {
                if (singleton == null) {
                    singleton = new Singleton7();
                }
            }
        }
        return singleton;
    }
}

4、饿汉模式——线程安全,但是无懒加载。

public class Singleton3 {
    private static Singleton3 instance = new Singleton3();

    private Singleton3() {
    }

    public static Singleton3 getInstance() {
        return instance;
    }
}

上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,
当系统中这样的类较多时,会使得启动速度变慢 。现在流行的设计都是讲“延迟加载”,我们可以在第一次使用的时候才初始化第一个该类对象。所以这种适合在小系统。

5、饿汉模式(变种)——线程安全,但是无懒加载。

public class Singleton4 {
    private static Singleton4 instance = null;
    static {
        instance = new Singleton4();
    }

    private Singleton4() {
    }

    public static Singleton4 getInstance() {
        return instance;
    }
}

本质上与第四中一样。

6、静态内部类——线程安全,实现懒加载。(推荐)

public class Singleton5 {
    private static class SingletonHolder {
        private static final Singleton5 INSTANCE = new Singleton5();
    }

    private Singleton5() {
    }

    public static final Singleton5 getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),
而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。 想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。

7、枚举——实现线程安全、懒加载、防止反序列化重新创建新的对象。本质上是最佳实现方式。

public enum Singleton6 {
    INSTANCE;
    public void whateverMethod() {
    }
}

讨论:
单例模式与垃圾回收
当一个单例的对象长久不用时,不会被jvm的垃圾收集机制回收。
http://blog.csdn.net/zhengzhb/article/details/7331354

参考博客:

http://cantellow.iteye.com/blog/838473
http://blog.csdn.net/zhengzhb/article/details/7331369

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值