单例模式:它是一种对象创建模式,用于产生一 个对象的具体实例,可以确保系统中一个类只产生一个实例。在Java语言中,这样的行为能 带来两大好处:
(
1
)对于频繁使用的对象,可以省去
new
操作花费的时间,这对于那些重量级对象而
言,是一笔非常可观的系统开销。
(
2
)由于
new
操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻
GC
压
力,缩短
GC
停顿时间。
因此对于系统的关键组件和被频繁使用的对象
,使用单例模式可以有效地改善系统的性
能。
public class Singleton {
private Singleton(){
System.out.println("Singleton is create"); //创建单例的过程可能会比较慢
}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
单例类必须要有一个private访问级别的构造函数,只有这样,才能确保单例不会在系统的其他代码内被实例化,这一点是相当重要的。
其次,instance
成员变量和
getInstance()
方法必须是
static
的。
恶汉模式:
public class Singleton {
private Singleton() {
//创建单例的过程可能会比较慢
System.out.println("Singleton is create");
}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
public static void createString() {
//这是模拟单例类扮演其他角色
System.out.println("createString in Singleton");
}
}
当使用
Singleton.createString()
执行任务时,程序输出以下内容:
Singleton is create
createString in Singleton
然此时并没有使用单例类,但它还是被创建出来
饿汉模式
public class LazySingleton {
private LazySingleton() {
//创建单例的过程可能会比较慢
System.out.println("LazySingleton is create");
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance() {
if (instance == null)
instance = new LazySingleton();
return instance;
}
}
getInstance()
方法必须是同步的,否则在多线程环境下,当线程1
正新建单例完成赋值操作前,线程
2
可能判断
instance
为
null
,故线程
2也将启动新建单例的程序,从而导致多个实例被创建,因此同步关键字是必需步骤。
改进版(兼顾懒汉和饿汉)
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;
}
}
使用内部类来维护单例的实例,当StaticSingleton
被加载时,其内部类并不会被初始化,故可以确保当StaticSingleton
类被载入
JVM
时不会初始化单例类,而当getInstance()
方法被调用时才会加载
SingletonHolder
,从而初始化
instance。同时,由于实例 的建立是在类加载时完成的,故天生对多线程友好,
getInstance()方法也不需要使用同步关键字。