单例模式的关键代码:构造函数是私有的。
要点:只有一个实例,必须自己创建自己唯一的实例,并给所有其他对象提供这一个实例。类提供了一种访问其唯一对象的方式,可以不借助实例化直接访问。
优点:内存中只有一个实例,避免重复创建和消费,减少内存开销;
避免对于资源的多重占用缺点:没有接口,不能继承
应用场景:生成唯一的序列号
程序中的配置,先用单例缓存起来,不用每次读取数据库。例如:oc2程序处理的开关
每次创建对象消耗资源过多,如I/O和数据库连接
创建一个单例类:
public class SingleObject { private static SingleObject instance = new SingleObject(); // 单例模式关键代码:私有的构造函数 这样的类就不会被实例化了 private SingleObject(){}; // 获取唯一的可用的对象 public static SingleObject getInstance(){ return instance; } public void showMessage(){ System.out.println("Hello Wold!"); } }
使用单例类:
public class TestDemo { // main函数 必须是 static,因为程序执行main方法时候没有创建任何对象 public static void main(String[] args){ // 获取唯一可用的对象 SingleObject singleObject = SingleObject.getInstance(); // 通过唯一对象提供所需方法 singleObject.showMessage(); } }
单例模式的多种实现方式:
选择单例模式创建方式的时候,需要考虑以下几个方面:
- 考虑对象创建时的线程安全问题;
- 考虑是否支持延迟加载;
- 考虑 getInstance() 性能是否高(是否加锁)。
懒汉模式:指的是在初始化的时候,不创建唯一实例,用时在创建。(必须加synchronize,否则多线程还是可能不唯一)
饿汉模式:指的是在初始化的时候,就创建唯一实例(static),无论是否用的到。1、懒汉式:
public class Singleton { private static Singleton instance; // 单例模式的关键代码,私有的构造函数,这样的类就不会被实例化了 private Singleton() {} // 获取唯一的可用的对象 // 懒汉式,线程不安全的,不支持多线程 public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } // 懒汉式,线程安全的,支持多线程,但加锁会影响效率 public static synchronized Singleton getInstance1() { if (instance == null) { instance = new Singleton(); } return instance; } }
2、饿汉式:
// 饿汉式,线程安全的,支持多线程,没有加锁,效率会提高 // 根据static的特性,instance2的对象在类初次被加载的时候就会被创建,可能造成垃圾对象。 private static Singleton instance2 = new Singleton(); public static Singleton getInstance2() { return instance2; }
3、双重锁式 (根据 volatile 特性)
// 双重锁,线程安全的,支持多线程,可以保持高性能 // 根据volatile的特性: private volatile static Singleton instance3; public static Singleton getInstance3(){ if(instance3 == null){ synchronized (Singleton.class){ if(instance3 == null){ instance3 = new Singleton(); } } } return instance3; }
4、静态内部类
对静态域使用延迟初始化public class Singleton { private static class SingleHolder{ private static final Singleton instance = new Singleton(); } private Singleton (){} public static final Singleton getInstance4(){ return SingleHolder.instance; } }