javaEE-多线程案例-单例模式

目录

啥是设计模式?

一.饿汉式

实现步骤:

二.懒汉式

实现步骤:

三、懒汉式优化1

四.懒汉式优化2

五.懒汉式优化3

总代码:


单例模式是一种设计模式。

啥是设计模式?

设计模式好⽐象棋中的"棋谱".红⽅当头炮,⿊⽅⻢来跳.针对红⽅的⼀些⾛法,⿊⽅应招的时候有⼀ 些固定的套路.按照套路来⾛局势就不会吃亏。软件开发中也有很多常⻅的"问题场景".针对这些问题场景,⼤佬们总结出了⼀些固定的套路.按照这个套路来实现代码,也不会吃亏。

单例模式能够保证在线程中只创建唯一一份实例,不会创建出多份实例。

一.饿汉式

类加载的同时,创建实例。

实现步骤:

1.在类内实例化一个 私有,静态 的该类实例。

2.将构造器私有化。

3.提供一个公共的方法,返回该类的实例化对象。

代码展示:

java 复制代码
/**
 *  //单例模式
 *    饿汉式
 */
class Instance{
    //1.实例化Instance线程,将其设为私有,静态
    private static Instance single=new Instance();
    //2.私有化构造器
    private Instance(){
    }
    //3.提供公共方法,返回类内创建的实例对象
    public static Instance getInstance(){
        return single;
    }
}

二.懒汉式

类加载的时候不会创建实例,第一次使用的时候才创建实例.

实现步骤:

1.创建私有,静态该类对象single,并设为null.

2.将构造器私有化。

3.提供公共方法,判断该类是否已经被创建,若single=null,则实例化对象,否则,直接返回single实例。

代码展示:

java 复制代码
class InstanceLazy1{
    // 1.创建该类对象,设为私有,静态
    // 先不实例化 将其设为null
    private static InstanceLazy1 single=null;
    //2.将构造器私有化
    private InstanceLazy1(){}
    //3.提供公共的方法,判断该类是否被实例化过
    //若未被实例化,则实例化对象,
    //否则直接返回single
    public static InstanceLazy1 getInstance(){
        if(single==null){
            return new InstanceLazy1();
        }
        return single;
    }
}

三、懒汉式优化1

在单线程下,懒汉式是线程安全的,但是若是在多线程下,懒汉模式就可能出现线程安全问题。

在两个线程t1,t2下:

为防止在多线程下,创建出多个对象,要使用synchronized锁,将if和new打包成一个原子的,在判断之前,先上锁,这样就能避免在第一次创建对象的时候,引发线程安全问题。

(这里创建多个对象虽然不会出现异常,无实质性错误,但是若创建的对象占用的内存空间是巨大的,此时若创建多个,就会带来非常大的代价,甚至有可能使内存满,)

但是,加锁之后,每次判断该类是否已被创建,都要先上锁,这势必会降低代码的运行效率,且可能出现 线程安全 只可能发生在第一次要创建对象的时候。

四.懒汉式优化2

为提高效率,在上锁之前,先判断是否是否创建过对象。若未创建,再上锁,再次判断是否实例化了对象。注意两次判断的作用是不同的。

第一次判断是为了提高代码执行效率,第二次是判断是否已创建对象。

五.懒汉式优化3

指令重排序问题也有可能引发线程安全问题.

指令重排序:代码优化的一种方式,调整代码的执行顺序,在原来逻辑不变的前提下,提高代码的执行效率。

可以使用volatile关键字来避免底层自动进行指令重排序.

懒汉式可能发生指令重排序问题是在创建对象的时候:

创建对象,分为三步:

1.申请一段内存空间

2.在这个内存上调用构造方法,创建出这个实例

3.将这个内存地址赋给single引用变量.

正常情况下,是按照1 2 3 来执行的,但有时会按照1 3 2来执行,也能创建出实例对象,这就是指令从排序.

但是在多线程下,若按照1 3 2来执行 就会引发线程安全问题.

这里,在代码重排序后创建出来的single对象,属于未初始化的全"0"值,若该对象中有属性或方法,一旦在后面的代码使用该对象,就可能会报错!!!

在single对象处加上volatile关键字修饰,就能禁止代码重排序,防止这样的对象被创建,解决线程安全问题。

总代码:

java 复制代码
/**
    单例模式
    懒汉式
/
class Instance{
    //1.实例化Instance线程,将其设为私有,静态
    private static Instance single=new Instance();
    //2.私有化构造器
    private Instance(){
    }
    //3.提供公共方法,返回类内创建的实例对象
    public static Instance getInstance(){
        return single;
    }
}

/**
 * 单例模式
 * 饿汉式 优化版
 */
class InstanceLazy{
    // 定义该类对象,设为私有,静态
    // 先不实例化对象 将其设为null

    //优化3:为防止出现 指令重排序问题, 防止出现线程安全问题
    // 给single对象 加volatile关键字,底层不再进行指令重排序
    private static volatile InstanceLazy single=null;
    //将构造器私有化
    private InstanceLazy(){}
    //提供获取对象的公共方法,在方法内创建对象
    public static InstanceLazy getInstance(){
        Object locker=new Object();
        //判断
        // 若还未实例化对象,就实例化对象,
        if(single==null){//优化2:当第一次创建后,之后就不用再判断了,也就不用再加锁了,
                        //为了提高代码的效率,先判断一下,若不为空,则不再加锁,直接返回对象
            synchronized(locker){//懒汉式 优化1 :为防止出现线程安全问题
                                //将判断为空和创建新线程,设置为一个 原子的
                if(single==null){
                    return new InstanceLazy();
                }
            }
        }
        //若已创建过对象,就直接返回创建过的对象
        return single;
    }
}
/**
    测试用例
/
public class Thread{
    public static void main(String[] args) {

        Instance instance1=Instance.getInstance();
        Instance instance2=Instance.getInstance();
        System.out.println(instance1==instance2);//true 这两个对象是同一个对象实例

        InstanceLazy single3=InstanceLazy.getInstance();
        InstanceLazy single4=InstanceLazy.getInstance();
        System.out.println(single3==single4);//true single1和single2是同一个对象
    }
}
相关推荐
小李不想输啦11 分钟前
什么是微服务、微服务如何实现Eureka,网关是什么,nacos是什么
java·spring boot·微服务·eureka·架构
张铁铁是个小胖子12 分钟前
微服务学习
java·学习·微服务
ggs_and_ddu12 分钟前
Android--java实现手机亮度控制
android·java·智能手机
敲代码娶不了六花2 小时前
jsp | servlet | spring forEach读取不了对象List
java·spring·servlet·tomcat·list·jsp
Yhame.2 小时前
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
java·开发语言
是小崔啊3 小时前
开源轮子 - EasyExcel02(深入实践)
java·开源·excel
mazo_command4 小时前
【MATLAB课设五子棋教程】(附源码)
开发语言·matlab
myNameGL4 小时前
linux安装idea
java·ide·intellij-idea
IT猿手4 小时前
多目标应用(一):多目标麋鹿优化算法(MOEHO)求解10个工程应用,提供完整MATLAB代码
开发语言·人工智能·算法·机器学习·matlab
青春男大4 小时前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse