设计模式之单例模式

什么是设计模式
设计模式是经常使用、大多数人知道,有特定目录的代码设计经验。设计模式可以提高代码可维护性,可提升代码运行效率,也能提高系统可靠性。设计模式可以分为三类,分别是创建型、结构型和行为型。以下就单例模式简要概述。

什么是单例模式
单例模式涉及到一个类,这个类创建自己的对象,任何时候有且只创建一个对象。单例模式也是属于创建型模式,是提供创建对象的最佳方式。

单例模式创建方式
单例对象的创建方式有饿汉模式、懒汉模式、双重校验锁、枚举等。

小试牛刀
下面分别用懒汉模式、饿汉模式、双重检验锁、枚举进行简要实战
1、懒汉模式
实例:

/**
 * 懒汉模式
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 9:25
 */
public class LazySingleModel {
    /**
     * 私有化实例接收
     */
    private static LazySingleModel instance;

    /**
     * 构造函数私有化
     */
    private LazySingleModel(){};

    /**
     * 线程不安全
     * @return
     */
    public static LazySingleModel getInstanceByNotSec(){
        if(Objects.isNull(instance)){
            instance = new LazySingleModel();
        }
        return instance;
    }

    /**
     * 线程安全
     * synchronized 锁会增加性能开销
     * @return
     */
    public static synchronized LazySingleModel getInstanceBySec(){
        if(Objects.isNull(instance)){
            instance = new LazySingleModel();
        }
        return instance;
    }
}

测试:

/**
 * 测试单例模式
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 9:30
 */
@Slf4j
@SpringBootTest
public class TestSingleModel {

    @SneakyThrows
    @Test
    public void testLazySingle(){
        //同步
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i= 0;i<5;i++){
            MyThread myThread = new MyThread(countDownLatch);
            myThread.start();
            countDownLatch.countDown();
        }
    }

    class MyThread extends Thread{

        private CountDownLatch countDownLatch;

        MyThread(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            try {
                countDownLatch.await();
                //线程不安全的测试对象pub.iit.testdemo.single.LazySingleModel@f8270d2
                //线程不安全的测试对象pub.iit.testdemo.single.LazySingleModel@4be8a962
                //线程不安全的测试对象pub.iit.testdemo.single.LazySingleModel@6f85a94
                //线程不安全的测试对象pub.iit.testdemo.single.LazySingleModel@7ea84aaf
                //线程不安全的测试对象pub.iit.testdemo.single.LazySingleModel@f8270d2
                //log.error("线程不安全的测试对象{}",LazySingleModel.getInstanceByNotSec());
                
                
                //线程安全的测试对象pub.iit.testdemo.single.LazySingleModel@347e8c13
                //线程安全的测试对象pub.iit.testdemo.single.LazySingleModel@347e8c13
                //线程安全的测试对象pub.iit.testdemo.single.LazySingleModel@347e8c13
                //线程安全的测试对象pub.iit.testdemo.single.LazySingleModel@347e8c13
                //线程安全的测试对象pub.iit.testdemo.single.LazySingleModel@347e8c13
                log.error("线程安全的测试对象{}",LazySingleModel.getInstanceBySec());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2、饿汉模式
实例:

/**
 *
 * 饿汉模式
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 10:16
 */
public class HungrySigleModel {

    /**
     * 直接实例化
     */
    private static HungrySigleModel instance = new HungrySigleModel();

    /**
     * 构造函数私有化
     */
    private HungrySigleModel(){};


    /**
     * 线程安全
     * @return
     */
    public static HungrySigleModel getInstance(){
        return instance;
    }
}

测试:

/**
 * 测试单例模式
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 9:30
 */
@Slf4j
@SpringBootTest
public class TestSingleModel {

    @Test
    public void testHungrySingle(){
        //同步
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i= 0;i<5;i++){
            MyThread myThread = new MyThread(countDownLatch);
            myThread.start();
            countDownLatch.countDown();
        }
    }

    
    class MyThread extends Thread{

        private CountDownLatch countDownLatch;

        MyThread(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            try {
                countDownLatch.await();
                //线程安全的测试对象:pub.iit.testdemo.single.HungrySigleModel@1da95e6d
                //线程安全的测试对象:pub.iit.testdemo.single.HungrySigleModel@1da95e6d
                //线程安全的测试对象:pub.iit.testdemo.single.HungrySigleModel@1da95e6d
                //线程安全的测试对象:pub.iit.testdemo.single.HungrySigleModel@1da95e6d
                //线程安全的测试对象:pub.iit.testdemo.single.HungrySigleModel@1da95e6d
                System.err.println("线程安全的测试对象:"+HungrySigleModel.getInstance());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3、双重校验锁
实例:

/**
 * 双重校验锁
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 10:25
 */
public class DoubleLockSingleModel {

    /**
     * 实体可见
     */
    private static volatile DoubleLockSingleModel instance;

    /**
     * 构造私有化
     */
    private DoubleLockSingleModel(){};

    /**
     * 双重校验锁 线程安全
     * @return
     */
    public static DoubleLockSingleModel getInstance(){
        if(Objects.isNull(instance)){
            synchronized (DoubleLockSingleModel.class){
                if(Objects.isNull(instance)){
                    instance = new DoubleLockSingleModel();
                }
            }
        }
        return instance;
    }

}

测试:

/**
 * 测试单例模式
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 9:30
 */
@Slf4j
@SpringBootTest
public class TestSingleModel {

    @Test
    public void testDoubleLock(){
        //同步
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i= 0;i<5;i++){
            MyThread myThread = new MyThread(countDownLatch);
            myThread.start();
            countDownLatch.countDown();
        }
    }


    class MyThread extends Thread{

        private CountDownLatch countDownLatch;

        MyThread(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            try {
                countDownLatch.await();
                //线程安全的测试对象:pub.iit.testdemo.single.DoubleLockSingleModel@50193d97
                //线程安全的测试对象:pub.iit.testdemo.single.DoubleLockSingleModel@50193d97
                //线程安全的测试对象:pub.iit.testdemo.single.DoubleLockSingleModel@50193d97
                //线程安全的测试对象:pub.iit.testdemo.single.DoubleLockSingleModel@50193d97
                //线程安全的测试对象:pub.iit.testdemo.single.DoubleLockSingleModel@50193d97
                System.err.println("线程安全的测试对象:"+ DoubleLockSingleModel.getInstance());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

4、枚举类型,天然单例,因为枚举只会实例化一次
实例:

/**
 * 枚举单例
 * 天然线程安全,推荐使用
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 10:33
 */
public class EnumSingleModel {
    /**
     * 构造私有
     */
    private EnumSingleModel(){}

    enum EnumModel{
        INSTANCE;
        private EnumSingleModel enumSingleModel;

        private EnumModel(){
            enumSingleModel = new EnumSingleModel();
        }
    }

    /**
     * 获取对象
     * @return
     */
    public static EnumSingleModel getInstance(){
        return EnumModel.INSTANCE.enumSingleModel;
    }
}

测试:

/**
 * 测试单例模式
 * @author senfel
 * @version 1.0
 * @date 2022/8/10 9:30
 */
@Slf4j
@SpringBootTest
public class TestSingleModel {

    @Test
    public void testEnumSingle(){
        //同步
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for(int i= 0;i<5;i++){
            MyThread myThread = new MyThread(countDownLatch);
            myThread.start();
            countDownLatch.countDown();
        }
    }


    class MyThread extends Thread{

        private CountDownLatch countDownLatch;

        MyThread(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            super.run();
            try {
                countDownLatch.await();
                //线程安全的测试对象:pub.iit.testdemo.single.EnumSingleModel@5f2d78c3
                //线程安全的测试对象:pub.iit.testdemo.single.EnumSingleModel@5f2d78c3
                //线程安全的测试对象:pub.iit.testdemo.single.EnumSingleModel@5f2d78c3
                //线程安全的测试对象:pub.iit.testdemo.single.EnumSingleModel@5f2d78c3
                //线程安全的测试对象:pub.iit.testdemo.single.EnumSingleModel@5f2d78c3
                System.err.println("线程安全的测试对象:"+ EnumSingleModel.getInstance());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小沈同学呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值