Java设计模式之单例模式

单例设计模式

所谓的单例模式就是,采取一定的方法保证某个类在整个软件只有一个实例,并且该类提供一个获取其唯一实例的方法。

单例模式的常见实现方式有8种,分别为饿汉式(两种),懒汉式(五种),枚举式。

一、饿汉式

1、静态常量实现

public class SingletonHungry1 {

    private static SingletonHungry1 mInstance = new SingletonHungry1();

    private SingletonHungry1() {
    }

    public static SingletonHungry1 getInstance() {
        return mInstance;
    }
}

优点:写法比较简单,在类装载的时候就完成了实例化,避免了线程同步问题。

缺点:在类装载的时候就完成了实例化,没有到达懒加载的效果,如果从始至终未使用过这个实例,则会造成内存浪费。

2、静态代码块实现

public class SingletonHungry2 {

    private static SingletonHungry2 mInstance;

    static {
        mInstance = new SingletonHungry2();
    }

    private SingletonHungry2() {
    }

    public static SingletonHungry2 getInstance() {
        return mInstance;
    }
}

优缺点与静态常量实现相同。

二、懒汉式

1、普通懒汉式实现(线程不安全)

public class SingletonLazy1 {

    private static SingletonLazy1 mInstance;

    private SingletonLazy1() {
    }

    public static SingletonLazy1 getmInstance() {
        if (mInstance == null) {
            mInstance = new SingletonLazy1();

        }
        return mInstance;
    }
}

优点:达到了懒加载的效果,但是只能在单线程下使用。

缺点:如果在多线程下,一个线程进入了if判断语句块,但还未来得及往下执行,同时另一个线程也通过了这个判断语句,这时会产生多个实例。

2、同步方法实现(线程安全)

public class SingletonLazy2 {

    private static SingletonLazy2 mInstance;

    private SingletonLazy2() {
    }

    public static synchronized SingletonLazy2 getmInstance() {
        if (mInstance == null) {
            mInstance = new SingletonLazy2();
        }
        return mInstance;
    }
}

优点:达到了懒加载的效果,并且保障了线程安全。

缺点:执行效率低,每次获取实例的时候都要对方法进行同步,但是我们只需要在实例初始化的时候同步就可以了。

3、同步代码块实现

public class SingletonLazy3 {

    private static SingletonLazy3 mInstance;

    private SingletonLazy3() {
    }

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

优点:无

缺点:本意是对同步方法实现方式进行优化,结果适得其反,不仅没有提升效率,反而使得线程不安全,因为只是对初始化的代码进行了同步,但是其他线程依然可以进入if判断,这种写法不能使用!

4、双重检查实现

public class SingletonLazy4 {

    private static volatile SingletonLazy4 mInstance;

    private SingletonLazy4() {
    }

    public static SingletonLazy4 getmInstance() {
        if (mInstance == null) {
            synchronized (SingletonLazy4.class) {
                if (mInstance == null) {
                    mInstance = new SingletonLazy4();
                }
            }
        }
        return mInstance;
    }
}

优点:实现了懒加载的效果,并且保障了是线程安全的,推荐使用。

不要忘记使用volatile关键字,volatile可以保证对象的原子性,当某个线程改变单例对象时可以保证单例在其他线程实时同步更新。如果不加volatile关键字可能导致线程获取单例为null。

5、静态内部类实现

public class SingletonLazy5 {


    private SingletonLazy5() {
    }

    static class SingleInstance {
        private static SingletonLazy5 INSTANCE = new SingletonLazy5();
    }

    public static SingletonLazy5 getInstance() {
        return SingleInstance.INSTANCE;
    }
}

优点:保证了线程安全,利用静态内部类特点实现了懒加载,效率高。推荐使用。

1)这种方式采取了类装载机制来保证初始化实例时只有一个线程。

2)静态内部类SingleInstance在SingleLazy5装载时并不会立即实例化,而是在调用了getInstance()方法时才会进行装载,从而完成单例类的实例化。

3)类的静态属性只会在第一次加载类的时候初始化,JVM帮我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

三、枚举式

1、枚举式

public enum SingletonEnum {

    //单例本身
    INSTANCE;

    public void doSome() {
        System.out.println("~~~");
    }
}

优点:借助jdk1.5添加的枚举实现单例模式,不仅能避免多线程同步问题,还能防止反序列化重新创建新的对象,Effective Java作者提倡的方式,推荐使用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值