6.单例模式有几种写法?

本文详细介绍了 Java 中的四种单例模式实现:基础饱汉模式、线程安全的饱汉模式、双重检查锁的饱汉模式以及 volatile 修饰的饱汉模式。此外,还讲解了饿汉模式和 Holder 模式的实现与特性,探讨了它们在多线程环境下的性能表现和适用场景。通过对各种单例模式的对比,有助于开发者选择合适的单例实现方式。
摘要由CSDN通过智能技术生成

(1)饱汉模式
1.1基础饱汉模式
程序启动时并不着急进行初始化单例,等调用到获取实例的方法时再进行初始化,即为“懒加载”。核心为“懒加载”,优点是启动速度快、节省资源,缺点是写起来麻烦且线程不安全。

public class Singleton1 {
  private static Singleton1 singleton = null;
  private Singleton1() {
  }
  public static Singleton1 getInstance() {
    if (singleton == null) {
      singleton = new Singleton1();
    }
    return singleton;
  }
}

1.2饱汉模式-变种1
在getInstance()方法上添加synchronized关键字修饰,这样能保证真正的线程安全,但是缺点是并发性能极差,退化成串行,就算初始化以后,synchronized的锁也无法避开,可以在性能不敏感场景下使用。

public class Singleton1_1 {
  private static Singleton1_1 singleton = null;
  private Singleton1_1() {
  }
  public synchronized static Singleton1_1 getInstance() {
    if (singleton == null) {
      singleton = new Singleton1_1();
    }
    return singleton;
  }
}

1.3饱汉模式-变种2
双重检查锁(Double Check Lock,简称DCL),表面上懒加载+线程安全,但是由于指令重排,线程仍然不安全。

public class Singleton1_2 {
  private static Singleton1_2 singleton = null;

  public int f1 = 1;   // 触发部分初始化问题
  public int f2 = 2;
  private Singleton1_2() {
  }
  public static Singleton1_2 getInstance() {
    // may get half object
    if (singleton == null) {
      synchronized (Singleton1_2.class) {
        if (singleton == null) {
          singleton = new Singleton1_2();
        }
      }
    }
    return singleton;
  }
}

1.4饱汉模式-变种3
在变种2的基础上在instance上增加volatile关键字。在多线程环境下,变种3更适合性能敏感的场景。

public class Singleton1_3 {
  private static volatile Singleton1_3 singleton = null;

  public int f1 = 1;   // 触发部分初始化问题
  public int f2 = 2;
  private Singleton1_3() {
  }
  public static Singleton1_3 getInstance() {
    if (singleton == null) {
      synchronized (Singleton1_3.class) {
        // must be a complete instance
        if (singleton == null) {
          singleton = new Singleton1_3();
        }
      }
    }
    return singleton;
  }
}

(2)饿汉模式
在类加载时就初始化单例,在调用到获取实例的方法时直接返回即可。优点是天生的线程安全(得益于类加载机制),缺点是如果一直不使用单例的话比较耗费资源。

public class Singleton2 {
  private static final Singleton2 singleton = new Singleton2();
  private Singleton2() {
  }
  public static Singleton2 getInstance() {
    return singleton;
  }
}

值得注意的时,单线程环境下,饿汉与饱汉在性能上没什么差别;但多线程环境下,由于饱汉需要加锁,饿汉的性能反而更优。
(3)Holder模式
Holder模式的核心为饿汉模式的静态变量,保证了线程安全,同时通过静态Holder类持有真正实例,间接实现了懒加载。

public class Singleton3 {
  private static class SingletonHolder {
    private static final Singleton3 singleton = new Singleton3();
    private SingletonHolder() {
    }
  }
  private Singleton3() {
  }

  /**
  * 勘误:多写了个synchronized。。
  public synchronized static Singleton3 getInstance() {
    return SingletonHolder.singleton;
  }
  */
  public static Singleton3 getInstance() {
    return SingletonHolder.singleton;
  }
}

(4)枚举模式
代码量比饿汉模式更少,但用户只能直接访问实例Singleton4.SINGLETON,牺牲了静态工厂方法的优点,无法实现懒加载。

public enum Singleton4 {
  SINGLETON;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis中批量更新对象的Mapper.xml也有几种常见的写法,下面是其中几种常见的写法及其优缺点: 1. 使用foreach循环进行批量更新: ```xml <update id="batchUpdate" parameterType="java.util.List"> <foreach collection="list" item="item" separator=";"> UPDATE table_name SET column1 = #{item.property1}, column2 = #{item.property2}, ... WHERE primary_key = #{item.primaryKey} </foreach> </update> ``` 优点:简单直观,易于理解和实现。 缺点:每条记录都会生成一个SQL语句,可能会导致性能问题。 2. 使用CASE WHEN语句进行批量更新: ```xml <update id="batchUpdate" parameterType="java.util.List"> UPDATE table_name SET column1 = CASE primary_key <foreach collection="list" item="item" separator=" "> WHEN #{item.primaryKey} THEN #{item.property1} </foreach> ELSE column1 END, column2 = CASE primary_key <foreach collection="list" item="item" separator=" "> WHEN #{item.primaryKey} THEN #{item.property2} </foreach> ELSE column2 END, ... WHERE primary_key IN <foreach collection="list" item="item" separator="," open="(" close=")"> #{item.primaryKey} </foreach> </update> ``` 优点:减少了SQL语句的数量,提高性能。 缺点:SQL语句较长,可读性稍差。 3. 使用MyBatis提供的批量更新方法: ```java void batchUpdate(List<YourObject> list); ``` 优点:MyBatis提供了专门的批量更新方法,可以更方便地进行批量更新操作。 缺点:需要在Mapper接口中定义新的方法。 选择哪种写法取决于具体的需求和性能要求。如果数据量较小,可以选择第一种或第二种写法;如果数据量较大,性能要求较高,可以选择第三种写法。此外,还可以根据具体情况对SQL语句进行优化,比如使用JDBC的批处理等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值