一、单例模型具备条件:

1、​私有的构造方法

2、instance(单一实例,static)和getInstance(获取实例的方法,static)必须是​static

二、下面三种不同层次单例模型代码评价:

第一种,通过测试发现,虚拟机​加载类的时候单例就会被初始化​,有些比较费时的类,我们需要使用时才加载(比如:数据库连接,开机加速等),这时候就不太适合用这种方式

第二种,通过测试发现虚拟机加载类的时候不会初始化,只有调用了获取实例的方法时才会实例化,如果已经实例化的直接拿来用,实现了​懒加载​,但采用了​synchronized​同步的方式,性能会有所下降

第三种,通过测试发现,实现了懒加载的功能(​静态内部类​),也解决了第二种性能下降的问题。其实代理模型等也是可以实现的

三、总结:​我们可以通过优化代码来实现性能最佳的单例模型类​。推荐使用第三种方式,如果不是很费时的单例第一种也没关系。今天不举spring或jdk单例模型的实现,因为单例很好理解。值得注意的是,通过反射强制访问等,可能会破坏单例,但是是有办法避免的,后面有机会再做介绍。

四、单例模型未优化的例子(原始)

public class Singleton {

//static

private ​static ​Singleton instance = new Singleton();

//私有构造方法

private ​Singleton() {

}

//static

public ​static ​Singleton getInstance() {

return instance;

}

}

五、下面是三种不同水平的单例代码(第三种性能最佳)

1)第一种:(上例及下面这个例子分析),虚拟机加载的时候就会初始化

public class SingletonObject {

        private static SingletonObject instance = new SingletonObject();

        private SingletonObject() {

System.out.println("SingletonObject is created");

}


public static SingletonObject getInstance() {

return instance;

}

//​单独调用此方法(SingletonObject.otherMethod())​时,​”SingletonObject is created​“也会被打印,说明虚拟机加载的时候就会初始化

public static void otherMethod() {

System.out.println("this is other method");

}

}

2)第二种:​使用synchronized同步,虚拟机加载的时候不初始化,调用getInstance方法时才初始化

public class LazilySingletonObject {

private static LazilySingletonObject ​instance ​= null;

private LazilySingletonObject() {

System.out.println("LazilySingletonObject is created");

}

/*

* 这里必须同步锁synchronized

*/

public static ​synchronized ​LazilySingletonObject getInstance() {

if (null == instance) {

instance = new LazilySingletonObject();

}

return instance;

}

//​单独调用此方法(LazilySingletonObject.otherMethod())时,"LazilySingletonObject is created"不会被答应,说明单例没有实例化

public static void otherMethod() {

System.out.println("this is other method");

}

}

3)第三种:使用静态内部类实现赖加载,不使用synchronized,这样可以优化性能

public class OptimizedLazilySingletonObject {


private OptimizedLazilySingletonObject() {

System.out.println("OptimizedLazilySingletonObject is created");

}

//静态内部类中持有这个对象

private static class SingletonHolder {

​private static OptimizedLazilySingletonObject instance = new OptimizedLazilySingletonObject();

​}


public static OptimizedLazilySingletonObject getInstance() {

return SingletonHolder.instance;

}


}


六、测试

public class SingletonTest {


public static void main(String[] args) {

/**

* 输出:Singleton is created

* 说明获取对象的时候私有方法需要调用(很好理解)

*/

//Singleton.getInstance();

/**

* 输出:SingletonObject is created

* this is other method

* 说明:即使调用这个类中的其他方法,类也会立即初始化

* 如果对于那种非常费时的初始化我们希望是用的时候才初始化(比如数据库连接等)

*/

SingletonObject.otherMethod();

/**

* 实现了赖加载,使用的时候才初始化,但是使用同步锁,性能会下降

*/

//LazilySingletonObject.getInstance();

/**

* 输出:this is other method

* 说明:不用的时候,单例不会初始化

*/

LazilySingletonObject.otherMethod();

/**

* 实现了赖加载,并没有影响性能

*/

OptimizedLazilySingletonObject.getInstance();

}


}