参考资料:《java程序性能优化》、网路资料
单例模式主要分为:懒汉模式和饿汉模式。当然,其中又有不同的细分和变种。
单例模式的主要优点:
- 对于频繁使用的对象,可以省略创建对象所花费的时间,特别对于那些重量级的对象。
- 减少new创建对象的操作,因而对于系统内存的使用频率也会降低,这将减轻GC压力,缩短GC的停顿时间。
释义:
为了减少创建对象的时间和GC的压力,我们需要将变量定义为static。当我们定义为static时,其会存储到静态域中,从而使“引用超出作用域后,GC不会销毁对象“。同时为了达到了“确保系统中一个类只产生一个实例“的目的,我们需要将该类的构造方法申明为private,以确保只能内部调用创建该类,而不允许外部直接创建。
/**
* 饿汉模式<br>
* 1、对于频繁使用的对象,可以省略创建对象所花费的时间,对于那些重量级对象而言,是非常可观的一笔开销<br>
* 2、由于new 操作次数的减少,因而对于系统内存的使用频率将会降低,这将减轻GC压力,缩短GC停顿时间<br>
* 3、缺点:无法对instance 实例做延迟加载。当调用该类中的方法时,该实例即被创建!
* 在一些地方,我们却需要实例仅仅在被调用getInstace时被创建。
* @see LazySingleton
* */
public class HungrySingleton extends Singleton{
private HungrySingleton(){
TestUtil.Println("当我创建此饿汉单例的时间为:" + new Date());
}
private static HungrySingleton instance = new HungrySingleton();
public static HungrySingleton getInstance(){
TestUtil.Println("当我调用饿汉方法的时间为:" + new Date());
return instance;
}
public static void otherMethod(){
TestUtil.Println("调用其他方法的时间为:" + new Date());
}
}
/**
* 懒汉模式:主要应用是为了做延迟加载!<br>
* 1、对于静态成员变量instance 初始值赋予null,确保系统启动时没有额外负载。<br>
* 2、同步getInstance方法,以防止在多线程环境中,创建多个实例。<br>
* 缺点:在实际上,因为引入了同步关键字。因此在多线程环境中,他的耗时要远大于hungrySingleton<br>
* 方法:{@link StaticSingleton}。
* @see HungrySingleton
* */
public class LazySingleton extends Singleton{
private LazySingleton(){
TestUtil.Println("创建了懒汉模式在:" + new Date());
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance(){
if(instance == null)
instance = new LazySingleton();
TestUtil.Println("当我调用饿汉方法的时间为:" + new Date());
return instance;
}
public static void otherMethod(){
TestUtil.Println("调用其他的方法:" + new Date());
}
}
/**
* 改进版:懒汉模式<br>
* 1、当初始化的时候StaticSingleton不会初始化<br>
* 2、使用内部类初始化的过程中,不会产生多线程问题
* @see HungrySingleton
* */
public class StaticSingleton extends Singleton{
private StaticSingleton(){
TestUtil.Println("创建了StaticSingleton单例模式:" + new Date());
}
private static class SingletonHolder{
private static StaticSingleton instance = new StaticSingleton();
}
public static StaticSingleton getInstance(){
TestUtil.Println("当我调用StaticSingleton饿汉方法的时间为:" + new Date());
return SingletonHolder.instance;
}
}