(1) 直接加载,无论是否需要,只要类被虚拟机加载,这个单例就存在
class="java"> private static DirectSingleton directSingleton = new DirectSingleton(); public static DirectSingleton getInstance() { return directSingleton; } }
?这种方法的缺点是无法实现延迟加载,如果单例的创建过程很慢,而这个类除了创建单例以外还做了别的事情的话,可能导致所有用到这个单例类的地方都在创建单例而不管这个单例对象是否被用到。
(2)一种实现延迟加载的方式是在使用的时候创建单例对象,但是需要确保单例对象只被创建一次,因而需要使用synchronized关键字
public class LazySingletonUseSynchronize { private LazySingletonUseSynchronize(){ System.out.println("LazySingletonUseSynchronize"); } private static LazySingletonUseSynchronize lazySingleton = null; public static synchronized LazySingletonUseSynchronize getInstance(){ if(lazySingleton == null){ lazySingleton = new LazySingletonUseSynchronize(); } return lazySingleton; } }
?
?不给单例对象初始值,以确保系统没有额外的负担。虽然实现了延迟加载但是synchronized关键词的使用使得在多线程环境下,这种方式的耗时大大增加
?
(3)为了使用延迟加载,但是又不想使用同步可改进为通过内部类加载的方式去初始化单实例对象。当类被加载时内部类不会被初始化。这样既不会在主类加载的时候初始化单例对象,也不需要使用同步关键词确保实例只创建一个,因为只要jvm加载内部类,里面的static变量就会被初始化。
public class LazySingletonUserInnerClass { private LazySingletonUserInnerClass(){ System.out.println("LazySingletonUserInnerClass"); } private static class LazySingletonInnerClass{ private static LazySingletonUserInnerClass lazySingleton = new LazySingletonUserInnerClass(); } public static LazySingletonUserInnerClass getInstance(){ return LazySingletonInnerClass.lazySingleton; } public static void main(String[] args) { LazySingletonUserInnerClass ss = getInstance(); LazySingletonUserInnerClass ss1 = getInstance(); } }
?
?