Modo singleton
Existem muitas maneiras de implementar o modo singleton: homem com fome, homem preguiçoso, enumeração, classe interna estática, etc.
Repostado de: https://www.jianshu.com/p/b8c578b07fbc
Por que usar o modo singleton?
Cenário Para algumas classes (principalmente classes de ferramentas), todo o sistema precisa apenas de uma instância para completar a tarefa, como: classe de impressão de log, obtenção de classe de pool de threads, etc.
vantagem
- Há apenas um objeto no sistema, o que economiza recursos do sistema, reduz a sobrecarga de criar e destruir objetos com frequência e melhora o desempenho do sistema.
Desvantagem
- Se o objeto instanciado não for utilizado por muito tempo, ele será considerado lixo pelo sistema e será reciclado, o que resultará na perda do estado do objeto.
Método para perceber
- Modo homem preguiçoso
/**
* <饿汉模式>
* <p>
* 类一旦加载就创建instance实例,getInstance时实例已经存在
*
* @author dkangel
*/
public class SingletonHungry {
private static final SingletonHungry instance = new SingletonHungry();
/**
* 私有构造方法,避免其他类创建实例
*/
private SingletonHungry() {
}
public static SingletonHungry getInstance() {
return instance;
}
}
- Modo homem faminto
/**
* <懒汉模式>
* 只有在getInstance时才去实例化instance
* <p>
* <应用场景>
* 除了初始化单例类时 即 创建单例外,继续延伸出来的是:单例对象 要求初始化速度快 & 占用内存小
*
* @author dkangel
*/
public class SingletonLazy {
/**
* volatile 保证指令重排序的正确性
*/
private volatile static SingletonLazy instance;
/**
* 私有构造方法,避免其他类创建实例
*/
private SingletonLazy() {
}
/**
* <双重校验锁机制>
* <p>
* 第一个if:若实例已经创建,则直接返回,无需加锁
* <p>
* 第二个if:避免多次创建实例
* 如果有两个线程同时调用getInstance()方法,线程A先获取到锁,线程B等待线程A释放锁
* 当线程A执行instance = new SingletonLazy();完毕,释放了锁,此时线程B获取到锁
* 假如没有第二个if判空,则线程B也会执行instance = new SingletonLazy();
* 这样就导致创建了多余的实例
*
* @return SingletonLazy
*/
public static SingletonLazy getInstance() {
if (instance == null) {
synchronized (SingletonLazy.class) {
if (instance == null) {
instance = new SingletonLazy();
}
}
}
return instance;
}
/**
* <同步锁>
* <p>
* 每次访问都要进行线程同步(即 调用synchronized锁)
* 造成过多的同步开销(加锁 = 耗时、耗能)
*
* @return SingletonLazy
*/
public static synchronized SingletonLazy getInstance1() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}