单例模式
单例对象的类必须保证只有一个实例存在。
许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为,比如全局信息配置。
1. 单例模式最简单的实现
public class Singleton {
private Singleton() {
System.out.println("Singleton is create");
}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
由私有构造方法和static来确定唯一性。
缺点:何时产生实例 不好控制
虽然我们知道,在类Singleton第一次被加载的时候,就产生了一个实例。但是如果这个类中有其他属性,比如:
public class Singleton {
public static int STATUS=1;
private Singleton() {
System.out.println("Singleton is create");
}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
当使用
System.out.println(Singleton.STATUS);
这个实例就被产生了。也许此时你并不希望产生这个实例。如果系统特别在意这个问题,这种单例的实现方法就不太好。
2. 第二种单例模式的解决方式(延迟加载)
public class Singleton {
private Singleton() {
System.out.println("Singleton is create");
}
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
}
让instance只有在调用getInstance()方式时被创建,并且通过synchronized来确保线程安全,这样就控制了何时创建实例。
这种方法是延迟加载的典型。
但是有一个问题就是,在高并发的场景下性能会有影响,虽然只有一个判断就return了,但是在并发量很高的情况下,或多或少都会有点影响,因为都要去拿synchronized的锁。
3. 第三种方式(高效)
public class StaticSingleton {
private StaticSingleton(){
System.out.println("StaticSingleton is create");
}
private static class SingletonHolder {
private static StaticSingleton instance = new StaticSingleton();
}
public static StaticSingleton getInstance() {
return SingletonHolder.instance;
}
}
由于加载一个类时,其内部类不会被加载。这样保证了只有调用getInstance()时才会产生实例,控制了生成实例的时间,实现了延迟加载。并且去掉了synchronized,让性能更优,用static来确保唯一性。