单例模式的本质是在运行过程中,某个类只能实例化一个对象;下面是单例模式最基本的实现方式
package com.fuck.singleton;
public class Singleton {
private Singleton(){
System.out.println("This is a single object");
}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
public static void createSingleton(){
System.out.println("Create singleton ");
}
public static void main(String[] args) {
Singleton.createSingleton();
}
}
运行结果:
很明显上面的代码中还没有使用到Singleton的实例,就实例化了一个对象;下面使用一种延迟实例化的方式实现,当使用到该对象的时候再实例。
package com.fuck.singleton;
public class LazySingleton {
private LazySingleton(){
System.out.println("This is a single object");
}
private static LazySingleton lazySingleton = null;
public static synchronized LazySingleton getInstance(){
if(null == lazySingleton){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
public static void createSingleton(){
System.out.println("Create singleton ");
}
public static void main(String[] args) {
LazySingleton.createSingleton();
}
}
运行结果:
上面的结果显示,没有使用到该对象就不实例化;这里需要注意:getInstance()必须是同步的,在多线程的环境下,线程1正在创建实例,完成赋值前,线程2可能判断lazySingleton为null,还会创建一个实例,这样就创建了两个实例,所以要加上synchronized关键字。使用synchronized关键字,可能效率比较低,可以使用内部类来维护实例,解决线程安全问题。
package com.fuck.singleton;
public class StaticSingleton {
private StaticSingleton(){
System.out.println("This is a single object");
}
private static class SingleHolder {
private static StaticSingleton staticSingleton = new StaticSingleton();
}
public static StaticSingleton getInstance(){
return SingleHolder.staticSingleton;
}
}
JVM在载入StaticSingleton类时,SingleHolder不会加载;当调用getInstance()时,SingleHolder类才加载,由于实例的创建在类加载之后,所以这里不会出现线程安全问题。