单例模式
一、前言
设计模式是前人工作的总结和提炼。通常,设计模式都是针对某一特定问题的成熟的解决方案。如果 能合理地使用设计模式,不仅能让系统更容易被他人理解,同时也能使系统拥有更加合理地结构。
单例模式是设计模式中最为普遍的模式之一。它是一种对象创建模式,用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。
有什么好处?
- 对于频繁使用的对象,可以省下创建对象所花费的时间。
- new的次数减少,因而对系统内存的使用频率也会降低,减轻GC压力,缩短GC停顿时间
什么时候用?
对于系统中的关键组件和被频繁使用的对象,使用单例模式可以有效的改善系统性能。
二、一个简单的单例模式
public class Singleton { //私有的构造方法 private Singleton(){ System.out.println("单例被创建"); } //类加载时创建 private static Singleton instance =new Singleton(); //外部程序获取实例的方法 public static Singleton getInstance(){ return instance; } public static void otherMethod() { System.out.println("我是Singleton的其他方法"); } }
首先单例模式必须要有一个private修饰的构造函数,这样才会确保单例不会被其他代码示例化,其次instance成员变量和getInstance方法必须是static的。
但是这个单例有个缺陷,就是由于instance变量是static的,所以当jvm加载单例类是,单例对象就会被创建,即我们还没有使用单例类,他就被创建出来了,当使用Singleton.otherMethod()时,程序输出
单例被创建
我是Singleton的其他方法
为了解决这个问题,提高系统在调用相关函数的反应数据,就需要引入延时加载机制
public class LazySingleton { private LazySingleton(){ System.out.println("单例被创建了"); } private static LazySingleton instance=null; public static synchronized LazySingleton getInstance(){ if(instance==null){ instance= new LazySingleton(); } return instance; } }
给静态初始化变量instance赋值为null,确保系统启动时没有额外的负载。在getInstance方法中判断instance变量是否存在,如果不存在则创立单例模式。要注意的是,getInstance方法加了synchronized关键字,因为可能出现多线程访问getInstance方法的情况,当线程1在创建单例时,在完成赋值操作前,线程2可能判断instance为null,故也创建一个实例对象。
但是为了使用延时加载引入了同步关键字反而降低了程序的性能,为了解决这个问题,需要对其进行改造
public class StaticSingleton { //私有的构造方法 private StaticSingleton(){ System.out.println("单例被创建"); } //静态内部类 private static class SingletonHolder{ private static StaticSingleton instance=new StaticSingleton(); } public static StaticSingleton getInstance(){ return SingletonHolder.instance; } }
使用内部类来维护单例实例,当StaticSingleton类被加载时,其内部类不会被初始化,也就不会初始化instance变量。只有当getInstance方法被条用是,才会加载SingletonHolder,初始化instance。由于实例的创建时在类加载的时候完成的,所以天生对多线程友好也就不用同步关键字。

浙公网安备 33010602011771号