Java23种设计模式之单例模式

本文详细介绍了Java中的23种设计模式之一——单例模式,包括饿汉式、懒汉式、线程安全的懒汉式、双重检查锁定的懒汉式以及静态内部类和枚举实现的单例模式。每种实现方式的优缺点及线程安全性进行了分析,为实际开发提供了参考。
摘要由CSDN通过智能技术生成

Java23种设计模式之单例模式

第一种(饿汉)

//饿汉试
class Singleton01 {
    private Singleton01() {
    }

    private static Singleton01 singleton = new Singleton01();

    public static Singleton01 getSingleton() {
        return singleton;
    }
}

这种方式基于classloder机制避免了多线程的同步问题,不过,singleton在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getSingleton方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化singleton显然没有达到lazy loading的效果。

第二种(饿汉)

class Singleton02 {
    private Singleton02() {
    }
    private static Singleton02 singleton = null;
    static {
        singleton = new Singleton02();
    }
    public static Singleton02 getSingleton() {
        return singleton;
    }
}

表面上看起来差别挺大,其实更第一种方式差不多,都是在类初始化即实例化singleton。

第三种(懒汉)

class Singleton03 {
    private Singleton03() {
    }

    private static Singleton03 singleton03;

    public static Singleton03 getSingleton() {
        if (singleton03 == null)
            singleton03 = new Singleton03();
        return singleton03;
    }
}

这种写法lazy loading很明显,但是缺点的是在多线程不能正常工作。

第四种(懒汉 线程安全 不推荐)

class Singleton04 {
    private Singleton04() {
    }

    private static Singleton04 singleton04;

    public static synchronized Singleton04 getSingleton() {
        if (singleton04 == null)
            singleton04 = new Singleton04();
        return singleton04;
    }
}

这种写法解决了第三种的的缺点,但是在效率上大打折扣,99%的几率都会去同步

第五种(懒汉 双重检查 线程安全 推荐)

class Singleton05 {
    private Singleton05() {
    }
// volatile可以保证即使java虚拟机对代码执行了指令重排序,也会保证它的正确性。
    private static volatile Singleton05 singleton05;

    public static Singleton05 getSingleton() {
        if (singleton05 == null)
            synchronized (Singleton05.class) {
                if (singleton05 == null) {
                    singleton05 = new Singleton05();
                }
            }
        return singleton05;
    }
}

这种写法解决了第四种的缺点,用两次判断来解决每次需要同步的问题.虽然使用了volatile 降低了效率,但是也无伤大雅.

第六种(静态内部类 线程安全 推荐)

class Singleton06 {
    private Singleton06() {
    }

    static class Singletons {
        private final static Singleton06 singleton06 = new Singleton06();
    }

    public static Singleton06 getSingleton() {
        return Singletons.singleton06;
    }
}

这种方式同样利用了classloder的机制来保证初始化Singleton06 时只有一个线程,Singleton06 类被装载了,singleton06不一定被初始化。因为Singletons 类没有被主动使用,只有显示通过调用getSingleton方法时,才会显示装载Singletons 类,从而实例化singleton06 。

第七种(枚举 线程安全 推荐)

enum Singleton07 {
    SINGLETON;

    public static Singleton07 getSingleton() {
        return SINGLETON;
    }
}

这种方式是Effective Java作者Josh Bloch 提倡的方式,最佳的单例实现模式就是枚举模式。利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题,而且还能防止反序列化重新创建新的对象。除此之外,写法还特别简单。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值