单例模式的定义:
:指一个类只有一个实例
单例模式的具体实现
需要:
(1)私有的构造方法,使其不能在类的外部通过new关键字实例化该类对象。
(2)私有的静态实例化对象,并且将其封装为private static类型。
(3)对外提供一个公共的访问方法,并返回该实例对象。
单例模式的两种实现:
第 1 种:饿汉式(立即加载):
饿汉式就是 使用类的时候已经将对象创建完毕(不管以后会不会使用到该实例化对象,先创建了再说。很着急的样子,故又被称为“饿汉模式”),常见的实现办法就是直接new实例化
public class Singleton { // 将自身实例化对象设置为一个属性,并用static、final修饰 private static final Singleton instance = new Singleton(); // 构造方法私有化 private Singleton() {} // 静态方法返回该实例 public static Singleton getInstance() { return instance; } }
“饿汉式”的优缺点:
优点:
实现起来简单,没有多线程同步问题。
缺点:
当类Singleton被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。
第 2 种:懒汉式(延迟加载):
该模式的特点 是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。
public class LazySingleton { private static volatile LazySingleton instance=null; //保证 instance 在所有线程中同步 private LazySingleton(){} //private 避免类在外部被实例化 public static synchronized LazySingleton getInstance() { //getInstance 方法前加同步 if(instance==null) { instance=new LazySingleton(); } return instance; } }
优点:在多线程情形下,保证了“懒汉模式”的线程安全。
缺点:众所周知在多线程情形下,synchronized方法通常效率低,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
最佳的单例模式的实现:
结合上面两种单例模式的实现 都存在缺陷 采用 DCL双检查锁机制(DCL:double checked locking)
public class Singleton { // 将自身实例化对象设置为一个属性,并用static修饰 private static Singleton instance; // 构造方法私有化 private Singleton() {} // 静态方法返回该实例 public static Singleton getInstance() { // 第一次检查instance是否被实例化出来,如果没有进入if块 if(instance == null) { synchronized (Singleton.class) { // 某个线程取得了类锁,实例化对象前第二次检查instance是否已经被实例化出来,如果没有,才最终实例出对象 if (instance == null) { instance = new Singleton(); } } } return instance; } }
上面是单例模式的最佳实现方式。内存占用率高,效率高,线程安全,多线程操作原子性。
使用场景:
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:
1.需要频繁实例化然后销毁的对象。
2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3.有状态的工具类对象。
4.频繁访问数据库或文件的对象。
5 当某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。