Java常见单例模式

一、介绍

有些时候我们需要只保存某个类的单个实例,叫做单例Singleton。比如反复的初始化和销毁对象会占用大量的资源,我们就适合使用单例模式。

二、饿汉模式

饿汉需要的是立刻马上就准备好食物,因此饿汉模式为事先创建好对象,等待使用。

public class SingletonDemo1 {

    private static SingletonDemo1 singletom = new SingletonDemo1();

    private SingletonDemo1() {
        // DO SOMETHING;
    }

    public static SingletonDemo1 getInstance() {
        return singletom;
    }
}

说明:类被加载的时候就初始化,可能会导致资源的浪费。

三、懒汉模式

懒汉可以理解为事情要拖到最后才去处理。因此懒汉模式事先不初始化,使用之前才创建对象。

public class SingletonDemo2 {

    private static SingletonDemo2 instance;

    private SingletonDemo2() {
        // DO SOMETHING;
    }

    public synchronized static SingletonDemo2 getInstance() {

        if (instance == null) {
            instance = new SingletonDemo2();
        }

        return instance;
    }
}

说明:根据是否包含synchronized会有两种不同的结果。

  • 不包含synchronized,低并发的时候可能没有问题,在高并发下 if (instance == null) 这个判断可能会出现问题,因为实例还没有初始化完,instance的值还是null,可能会有多个线程同时执行 instance = new SingletonDemp2() 这个语句,结果可能比资源浪费还要严重。
  • 包含synchronized,低并发没有问题,高并发下不会出现错误和资源浪费,但是处理会变成同步模式,导致效率问题。

四、静态内部类

public class SingletonDemo3 {

    private static class SingletonWrap {

        public static SingletonDemo3 instance = new SingletonDemo3();
    }


    private SingletonDemo3() {
        // DO SOMETHING;
    }

    public static SingletonDemo3 getInstance() {
        return SingletonWrap.instance;
    }
}

说明:没有明显的不足,跟饿汉模式比较接近,又能在使用的时候初始化

五、枚举

public enum SingletonDemo4 {

    INSTANCE;

    public void doSomething() {
        System.out.println("要实现的代码写在这个自定义方法里");
    }

    public static void main(String[] args) {
        SingletonDemo4.INSTANCE.doSomething();
    }
}

说明:没有明显的不足,不支持继承(但是使用继承的机会又比较少)

六、双重校验锁


public class SingletonDemo5 {

    private volatile static SingletonDemo5 instance;

    private SingletonDemo5() {
        // DO SOMETHING;
    }

    public synchronized static SingletonDemo5 getInstance() {

        if (instance == null) {
            synchronized (SingletonDemo5.class) {
                if (instance == null) {
                    instance = new SingletonDemo5();
                }
            }
        }

        return instance;
    }
}

说明:需要注意两个变化的地方。

  • volatile关键字,用来防止对象创建过程中因为指令重排,从而导致访问到未被初始化完成的对象。
  • 两次 if (instance == null) 判断,避免了多线程的排队问题,同时也避免了数据的多次初始化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值