23种设计模式之单例模式

本文详细介绍了Java中的单例模式,包括其特点、懒汉式和饿汉式的实现方式。针对线程安全问题,分析了简单懒汉式存在的并发问题,并通过实例演示了多个线程环境下可能产生的多个实例。最后,提出了使用同步锁和双重检查锁定来解决线程安全问题的优化方案,确保单例模式的正确实现。
摘要由CSDN通过智能技术生成

#单例模式

单例模式是java中最简单的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

单利模式的特点

  1. 构造方法私有化
  2. 提供一个返回单例对象本身的公共方法
  3. 提供一个静态的私有变量

单例模式分懒汉式和饿汉式

饿汉式

饿汉式在程序运行时加载,比较占内存空间

class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() {
        return instance;
    }
}

或者

class Singleton1 {
    private static Singleton1 instance;
    static {
        instance = new Singleton1();
    }
    public static Singleton1 getInstance() {
        return instance;
    }
}

懒汉式

懒汉式在需要的时候加载,即第一次实例化的时候加载

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

上诉为最简单的懒汉式,但是这种方法线程不安全
假设有两个线程,线程A和线程B,线程A实例化Singleton2时在if(instance == null)判断后中断,然后线程B也开始执行 if(instance == null),这个时候,instance还是null,判定为真,这时,A和B都实例化了Singleton2,创建了两个Singleton2的实例化对象
我们用代码测试一下
新建一个类,用于实例化Singleton2,并输出地址

class temp extends Thread {
    @Override
    public void run() {
        Singleton2 singleton = Singleton2.getInstance();
        System.out.println(singleton);
    }
}

然后测试

public static void main(String[] args) {
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
        new Thread(new temp()).start();
    }

执行结果为

Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@5ec1d90c
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@73248cf9
Test.Singleton2@4c6aca09
Test.Singleton2@73248cf9
Test.Singleton2@52a17671
Test.Singleton2@73248cf9

运行结果出现了多个地址,所以该方法线程不安全
既然线程不安全,我们就对该方法加锁

class Singleton3{
    private static Singleton3 instance;
    private Singleton3() {
    }
    public synchronized static Singleton3 getInstance() {
        if (instance == null) {
            instance = new Singleton3();
        }
        return instance;
    }
}

加锁之后,线程安全的问题就解决了,但新的问题又来了,因为对方法进行加锁,所以当一个线程运行该代码时,另一个线程就只能处于等待状态,大大降低了效率,所以又对该方法进行改进,把锁改为锁代码块儿

class Singleton4 {
    private static Singleton4 instance;
    private Singleton4() {
    }
    public static Singleton4 getInstance() {
        if (instance == null) {
            synchronized (Singleton4.class) {
                if (instance == null)
                    instance = new Singleton4();
            }
        }
        return instance;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值