网站导航app,网站制作做网站,wordpress slug,免费一级域名有哪些概念 保证指定的类只有一个实例#xff0c;不能创建出其他的实例
实现方式 1.饿汉模式 1.1 代码展示
package 设计模式;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-07-28* Time: 11:28*///单例模式#xff08;饿汉模式#xff09;
//保证…概念 保证指定的类只有一个实例不能创建出其他的实例
实现方式 1.饿汉模式 1.1 代码展示
package 设计模式;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-07-28* Time: 11:28*///单例模式饿汉模式
//保证Singleton类只有一个实例
//Singleton类中instance对象的创建时机在Singleton类被jvm加载的时候创建Singleton类会在第一次使用的时候被加载不一定是程序一启动的时候
class Singleton{//带有static的是类属性由于每个类的类对象是单例的所以类对象的属性static也是单例的private static Singleton instancenew Singleton();public static Singleton getSingleton(){return instance;} //当多个线程调用getSingleton方法相当于多个线程读取同一个变量这是线程安全的//由于要规定在类的外部不能实例化Singleton类型的对象所以要把构造函数改为私有的这样就在类外部就不能实例化Singleton类的对象了private Singleton(){};
}
public class Deom1 {public static void main(String[] args) {Singleton s1Singleton.getSingleton();Singleton s2Singleton.getSingleton();//Singleton s3new Singleton();System.out.println(s1s2);//System.out.println(s1s3);}
}1.2 Singleton类中instance对象的创建时机 Singleton类中instance对象的创建时机在Singleton类被jvm加载的时候创建Singleton类会在第一次使用的时候被加载不一定是程序一启动的时候 1.3 控制Singleton类的实例只有一个的核心步骤 1.3.1 在类属性static中进行创建带有static的是类属性由于每个类的类对象是单例的所以类对象的属性static也是单例的 1.3.2 提供一个获取这个对象的接口方便在类外调用这个对象 1.3.3 由于规定在类的外部不能实例化Singleton类型的对象所以要把构造函数改为私有的这样就在类外部就不能实例化Singleton类的对象了 1.4线程安全问题 饿汉模式实现单例模式是没有线程安全问题的因为多个线程调用getSingleton方法相当于多个线程读取instance引用的值没有涉及到多个线程进行修改所以没有线程安全问题 2.懒汉模式 2.1代码展示
package 设计模式;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-07-28* Time: 12:05*/
//单例线程懒汉模式
//SingletonLazy类中instance对象创建的时机在第一次调用getInstance方法时创建
class SingletonLazy{private static volatile SingletonLazy instancenull; //加上volatile避免内存可见性问题public static SingletonLazy getInstance(){if(instancenull){ //第一个条件判断是否需要加锁synchronized(SingletonLazy.class){ //第二个条件用于判断是否要创建对象if(instancenull){instancenew SingletonLazy();}}}return instance;}private SingletonLazy(){};
}
public class Demo2 {public static void main(String[] args) {SingletonLazy s1SingletonLazy.getInstance();SingletonLazy s2SingletonLazy.getInstance();System.out.println(s1s2);//SingletonLazy s3new SingletonLazy();}}2.2SingletonLazy类中instance对象创建的时机 在第一次调用getInstance方法时创建 2.3控制SingletonLazy类的实例只有一个的核心步骤 2.3.1在类属性static中进行创建声明带有static的是类属性由于每个类的类对象是单例的所以类对象的属性static也是单例的 2.3.2 提供一个实例化这个对象并返回这个对象的接口 2.3.3 由于规定在类的外部不能实例化Singleton类型的对象所以要把构造函数改为私有的这样就在类外部就不能实例化Singleton类的对象了 2.4 线程安全问题 懒汉模式存在线程安全问题 当多个线程判断instancenull可能多个线程都会判断为null值导致创建多个对象所以要对getInstance方法中的代码进行加锁将判断和创建对象两个操作变成一个原子性的操作 但实际上是需要一直加锁的吗不是的只有我们准备实例化instance对象的时候会出现线程安全问题当创建成功后instancenull此时多个线程都是获得instance引用的值不存在线程安全问题也就不需要加锁了所以要判断一下是否需要加锁当instance为null表示当前第一次准备创建该对象此时加锁控制只有第一个线程创建对象其余线程返回instance的值instance不为null说明instance对象已经创建成功多个线程都只是读取instance的值不存在线程安全问题所以不用加锁 加了锁以后该程序其实还有内存可见性问题因为在第一次调用getInstance方法创建对象后第二次去读取instance的值你不一定能读到最新的instance的值原因请看线程安全问题内存可见性所以要在instance变量声明的时候加上volatile易变的解决内存可见性问题 使用volatile不仅仅是为了预防出现内存可见性问题还要解决指令重排序问题指令重排序问题请看线程安全问题指令重排序