单例模式
package top.tobing.test;
/**
* @ClassName 饿汉式
* @Description TODO
* @Author wuning
* @Date 2022/12/20 9:37
* @Version 1.0
*/
public class Test {
private static Test test=new Test();
//构造方法私有,确保外界不能直接实例化
private Test(){
}
//通过公有的静态方法获取对象实例
private static Test getTest(){
return test;
}
}
package top.tobing.test;
/**
* @ClassName 懒汉式
* @Description TODO
* @Author wuning
* @Date 2022/12/20 9:39
* @Version 1.0
*/
//懒汉式单例模式
public class Test01 {
private static Test01 test01=null;
//构造方法私有,确保外界不能直接实例化
private Test01(){}
//可以使用synchronized关键字对静态方法 getInstance()进行同步,线程安全的的懒汉式单例模式代码
private synchronized Test01 getTest01(){
if (test01==null){
test01=new Test01();
}
return test01;
}
}
//双重检查锁定(推荐使用)
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
// 第一次检查,避免不必要的同步
if (instance == null) {
// 同步块
synchronized (Singleton.class) {
// 第二次检查,防止多线程下重复创建实例
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
解释双重检查锁定的代码:
声明volatile关键字:在双重检查锁定中,instance变量被声明为volatile,这样可以保证在多线程环境下对instance变量的可见性。当一个线程修改instance的值时,其他线程能够立即看到最新的值,避免了线程之间的数据不一致性。
第一次检查(if (instance == null)):在getInstance()方法中,首先检查instance是否为null,如果为null,才进入同步块进行实例的创建。这样可以避免不必要的同步操作,如果instance已经被初始化,后续线程直接返回已经存在的实例。
同步块:如果instance为null,线程进入同步块(synchronized (Singleton.class)),此时只有一个线程能够进入同步块,其他线程必须等待。
第二次检查(if (instance == null)):在同步块内部,再次检查instance是否为null,这是为了防止多线程环境下重复创建实例。因为在第一次检查之后,可能有其他线程已经进入同步块并创建了实例。
创建实例:如果第二次检查也确认instance为null,就在同步块内部创建实例。
双重检查锁定可以在多线程环境下保证单例模式的线程安全性,并且通过减少同步的范围来提高性能。但要注意,双重检查锁定只适用于Java 5及以上版本,因为在Java 5之前的JVM对volatile关键字的实现存在一些问题,可能会导致双重检查锁定失效。
单例模式是一种常用的设计模式,其优点和特点包括:
优点:
确保只有一个实例:单例模式确保在整个应用程序中只有一个实例存在,避免了多个实例的创建,节省了系统资源。
全局访问点:由于只有一个实例存在,并提供了一个全局访问点,可以方便地访问该实例,避免了对实例的重复创建和传递。
适用于资源共享:当有多个对象需要共享某一资源时,使用单例模式可以确保只有一个实例访问该资源,避免了资源的浪费和冲突。
避免全局变量:单例模式提供了一个全局访问点,可以取代全局变量的作用,使代码更加模块化和可维护。
特点:
私有构造方法:单例模式的类通常会将构造方法设为私有,以防止外部直接实例化该类。
静态实例:单例模式一般会在类内部创建一个私有的静态实例,并提供一个静态的获取实例的方法。
延迟初始化:懒汉式单例模式在第一次访问时才进行初始化,避免了不必要的资源消耗。而饿汉式单例模式则在类加载时就进行初始化,保证了线程安全,但可能影响应用启动速度。
需要注意的是,单例模式虽然具有很多优点,但也有其缺点。在某些场景下,单例模式可能会导致类的职责过于集中,违背了单一职责原则。另外,由于全局可访问的特性,滥用单例模式可能导致代码可维护性下降和单元测试困难。因此,在使用单例模式时,需要谨慎考虑,确保其在设计上是合理且必要的。
评论区