单例模式。

单例的用处

对于业务而言,有些数据在系统中只需要保存一份,那么就可以设计为单例模式。比如系统的配置信息类,Log日志或者全局唯一ID这种。

单例的实现

饿汉式

在类加载的期间,就已经将instance静态实例初始化好了。因此instance实例的创建是线程安全的。不过,这样的实现方式不支持延迟加载实例


public class IdGenerator { 
  private AtomicLong id = new AtomicLong(0);
  private static final IdGenerator instance = new IdGenerator();
  private IdGenerator() {}
  public static IdGenerator getInstance() {
    return instance;
  }
  public long getId() { 
    return id.incrementAndGet();
  }
}

懒汉式

相对于上者的优势就是支持延迟加载。但是也有明显的缺点,因为getInstance()这个方法被加了重量级锁。导致这个函数的并发很低。量化一下的话,并发度就是1,也就相当于串行操作了。如果被频繁的调用,那么就会导致性能瓶颈


public class IdGenerator { 
  private AtomicLong id = new AtomicLong(0);
  private static IdGenerator instance;
  private IdGenerator() {}
  public static synchronized IdGenerator getInstance() {
    if (instance == null) {
      instance = new IdGenerator();
    }
    return instance;
  }
  public long getId() { 
    return id.incrementAndGet();
  }
}

Double Check

既支持延迟加载也支持高并发。只要iinstance被创建之后,即使再调用getInstance()也不会再进入到加锁逻辑中了


public class IdGenerator { 
  private AtomicLong id = new AtomicLong(0);
  private static IdGenerator instance;
  private IdGenerator() {}
  public static IdGenerator getInstance() {
    if (instance == null) {
      synchronized(IdGenerator.class) { // 此处为类级别的锁
        if (instance == null) {
          instance = new IdGenerator();
        }
      }
    }
    return instance;
  }
  public long getId() { 
    return id.incrementAndGet();
  }
}

静态内部类

它的效果和double check一样,但是更加简单。

SingletonHolder是一个静态内部类,当外部类IdGenerator被加载的时候,并不会创建内部类的实例对象。只有当调用getInstance()方法的时候。内部类才会被加载,这个时候才会创建instance。instance的唯一性、创建过程的线程安全行,都由jvm来保证。


public class IdGenerator { 
  private AtomicLong id = new AtomicLong(0);
  private IdGenerator() {}

  private static class SingletonHolder{
    private static final IdGenerator instance = new IdGenerator();
  }
  
  public static IdGenerator getInstance() {
    return SingletonHolder.instance;
  }
 
  public long getId() { 
    return id.incrementAndGet();
  }
}

枚举


public enum IdGenerator {
  INSTANCE;
  private AtomicLong id = new AtomicLong(0);
 
  public long getId() { 
    return id.incrementAndGet();
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值