javaEE多线程2

发布时间:2023年12月23日

单例模式:保证某个类在程序中只存在唯一一份实例,即只能创建一个实例,不能创建多个对象

①饿汉模式:先创建实例

static:在JVM中,每个类的类对象只有一份,类对象里的这个成员也只有一个

实现只能让当前类只有一份实例,即将这个类中的构造函数的权限设置为private,则在类外就不能在创建新的实例,但是在当前的Singleton类里面还可以使用。因为private的权限是在当前类中

在main方法中通过类名+“·”调用getInstance获取到类里面的这个实例,此时的singleton1和singleton2指向的是同一个对象

②懒汉模式-单线程:非必要的时候,不创建实例,需要的时候再创建实例

在类的开始的时候,给instance赋值一个null,等需要的时候在进行创建实例

饿汉模式和懒汉模式的区别:

饿汉模式是在类的开始早早就创建了实例,而懒汉模式是在必要的时候才创建

在上面的代码中,饿汉模式的线程是安全的,因为getInstance()这个方法里面只是读取了instance这个实例,并没有对其进行修改。但是懒汉模式这个线程是不安全的,当有多个线程同时进行时,就会产生问题

下面这种情况就创建了两个实例

③懒汉模式-改进版

为了解决上面出现的问题,此时我们可以采用加锁的方式去解决这个问题

①采用synchronized对getInstance()实现加锁--使得判定操作和new操作变成原子的

但是加锁是一个比较抵消的操作,会出现阻塞等待。此时的代码中,任何一次调用getInstance()都会出现锁竞争。当已经出现首次创建时,后续调用getInstance()都只是在进行读取操作,就没有线程安全问题,就没有必要再进行加锁。所以在第一次创建实例的时候,不应该进行加锁,则对如下代码进行改进:

②双重if判定

此时两个if()语句所表达的意思并不是一样的,虽然两个代码一样,但是调用时间长结果就不一样

第一个if(instance == null)表示的时是否为第一次创建实例

第二个if(instance == null)表示是否需要加锁

比如:thread1线程正在加锁,thread2线程也想实现加锁,但是此时的锁正在被thread1线程占用着,所以出现了锁竞争,则thread2线程需要等待thread1线程释放锁。在thread1线程加锁后,执行了instance = new Singleton()这句代码,此时instance的值不在是null,thread2线程的instance的值也将被修改,当thread1线程释放锁时,由于instance的值不再是null,所以thread2线程将不再执行instance = new Singleton()这句代码

③加上volatile防止出现指令重排序

文章来源:https://blog.csdn.net/Good_CLL/article/details/132782381
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。