单例的用处
对于业务而言,有些数据在系统中只需要保存一份,那么就可以设计为单例模式。比如系统的配置信息类,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,也就相当于串行操作了。如果被频繁的调用php单线程,那么就会导致性能瓶颈
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();
}
}
(编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|