设计模式-懒汉式单例的2种方式(Java)

设计模式-懒汉式单例的2种方式

没加锁的懒汉式单例,单线程状态下没问题,但是多线程环境下,可能创建出来的就不是单例

package singleton;

public class LazySingleton {


    private LazySingleton() {
        System.out.println(Thread.currentThread().getName()+
        "线程不安全的单例模式,调用了构造器,被创建了");
    }

    private static LazySingleton INSTANCE = null;

    public static LazySingleton getInstance() {
        if (INSTANCE == null) {

            INSTANCE = new LazySingleton();
        }
        return INSTANCE;
    }

}

双检锁的方式

package singleton;

public class DclLazySingleton {
    private DclLazySingleton() {
        System.out.println(Thread.currentThread().getName()
        +"双检锁的懒汉,调用了构造器,被创建了");
    }

    private static volatile DclLazySingleton INSTANCE = null;

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

单线程环境两种懒汉单例测试

package singleton;

public class TestLazySingleton {
    public static void main(String[] args) {
        LazySingleton instance1 = LazySingleton.getInstance();
        LazySingleton instance2 = LazySingleton.getInstance();
        System.out.println("位置1:"+(instance1 == instance2));

        //DCL 双重检测锁的懒汉单例
        DclLazySingleton dclLazySingleton1 = DclLazySingleton.getInstance();
        DclLazySingleton dclLazySingleton2 = DclLazySingleton.getInstance();
        System.out.println("位置2:"+(dclLazySingleton1 == dclLazySingleton2));
    }
}

输出:
main线程不安全的单例模式,调用了构造器,被创建了
位置1true
main双检锁的懒汉,调用了构造器,被创建了
位置2true


多线程环境两种懒汉单例测试

package singleton;

public class TestMulThreadLazySingleton {


    public static void main(String[] args) {

        for (int i = 0; i < 50; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    LazySingleton.getInstance();
                }
            }).start();
        }
        System.out.println("--------------------------------");

        for (int i = 0; i < 50; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    DclLazySingleton.getInstance();
                }
            }).start();
        }
    }
}

输出:
Thread-0线程不安全的单例模式,调用了构造器,被创建了
Thread-11线程不安全的单例模式,调用了构造器,被创建了
Thread-9线程不安全的单例模式,调用了构造器,被创建了
Thread-1线程不安全的单例模式,调用了构造器,被创建了
Thread-5线程不安全的单例模式,调用了构造器,被创建了
Thread-8线程不安全的单例模式,调用了构造器,被创建了
Thread-6线程不安全的单例模式,调用了构造器,被创建了
Thread-3线程不安全的单例模式,调用了构造器,被创建了
Thread-2线程不安全的单例模式,调用了构造器,被创建了
Thread-7线程不安全的单例模式,调用了构造器,被创建了
Thread-10线程不安全的单例模式,调用了构造器,被创建了
Thread-4线程不安全的单例模式,调用了构造器,被创建了
--------------------------------
Thread-50双检锁的懒汉,调用了构造器,被创建了


总结:

通过以上的结果可以看到,在单线程环境下,两种方式的构造方法都只调用了一次。
但是在多线程环境下,第一个懒汉单例,没有加锁,他的构造方法被多个线程调用,导致创建了多个对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值