单例模式

单例模式:

  • 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

单例模式的特点:

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例

为什么使用单例模式:

  • 当我们需要确保某个类只要一个对象,或创建一个类需要消耗的资源过多,如访问IO和数据库操作等,这时就需要考虑使用单例模式了。
    比如说当我们使用多线程在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
    数据库连接实例主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为用单例模式来维护,就可以大大降低这种损耗。

单例模式
1、懒汉式,线程不安全:

这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

public class DanLiMoShi1 {
    private static DanLiMoShi1 instance;
    private DanLiMoShi1 (){}
    public static DanLiMoShi1 getInstance() {
        if (instance == null) {   //如果有了实例了,就不需要要创建了
            instance = new DanLiMoShi1();
        }
        return instance;
    }
    public void SayLove(){
        System.out.println("Love You Baby!");
    }
}
//测试一下
public class Test1 {
    public static void main(String[] args){
        DanLiMoShi1 danli1 = DanLiMoShi1.getInstance();
        DanLiMoShi1 danli2 = DanLiMoShi1.getInstance();
        if( danli1 == danli2 )
            System.out.println("我们是一样的");
        danli1.SayLove();
    }
}
//运行结果:
//我们是一样的
//Love You Baby!

2、懒汉式,线程安全:

必须加锁 synchronized 才能保证单例,但加锁会影响效率。

public class DanLiMoShi2 {
    private static DanLiMoShi2 instance;
    private DanLiMoShi2 (){}
    public static synchronized DanLiMoShi2 getInstance() {
        if (instance == null) {   //如果有了实例了,就不需要要创建了
            instance = new DanLiMoShi2();
        }
        return instance;
    }
    public void SayLove(){
        System.out.println("Love You Baby!");
    }
}

3、饿汉式,线程安全:

优点:没有加锁,执行效率会提高。

缺点:类加载时就初始化,浪费内存。

public class DanLiMoShi3 {
    private DanLiMoShi3() {
    }
    private static final DanLiMoShi3 single = new DanLiMoShi3();
    public static DanLiMoShi3 getInstance() {   //静态工厂方法
        return single;
    }
    public void SayLove(){
        System.out.println("Love You Baby!");
    }
}
测试:
public class Test3 {
    public static void main(String[] args) {
        DanLiMoShi3 danli1 = DanLiMoShi3.getInstance();
        DanLiMoShi3 danli2 = DanLiMoShi3.getInstance();
        if( danli1 == danli2 )
            System.out.println("我们是一样的");
        danli1.SayLove();
    }
}
//运行结果
//我们是一样的
//Love You Baby!

4、双检锁/双重校验锁(DCL,即 double-checked locking)

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

public class DanLiMoShi4 {
    private volatile static DanLiMoShi4 singleton;
    private DanLiMoShi4 (){}
    public static DanLiMoShi4 getInstance() {
        if (singleton == null) {
            synchronized (DanLiMoShi4.class) {
                if (singleton == null) {
                    singleton = new DanLiMoShi4();
                }
            }
        }
        return singleton;
    }
}
//测试
public class Test4 {
    public static void main(String[] args) {
        DanLiMoShi4 danli1 = DanLiMoShi4.getInstance();
        DanLiMoShi4 danli2 = DanLiMoShi4.getInstance();
        if( danli1 == danli2 )
            System.out.println("我们是一样的");
    }
}
//运行结果:
//我们是一样的

为什么这种能提升性能呢?
如果直接加锁,那么10个线程来了,那这10个线程需要排队;但是采用双检锁/双重校验锁的方式,10个线程来了,如果已经有实例了,直接返回实例,这样就不需要排队了,从而提高了性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值