单例模式
单例模式这边主要写单例模式的实现方式和总结:话不多说直接上代码:
单例模式之饿汉模式:
代码(Coding):
/** * 饿汉模式: 在类加载的时候就把对象给一并加载完成 因此不存在线程安全问题 具体实现如下: */ public class SingleTonDemo01 { // 1、私有化构造器 private SingleTonDemo01(){} // 2、定义静态变量 private static SingleTonDemo01 singleTonDemo01 = new SingleTonDemo01(); // 3、公开获取INSTANCE的方法 public static SingleTonDemo01 getInstance() { return singleTonDemo01; } }
优点:代码简洁 并且由于类加载的时候就将单例实例也给一起初始化出来,因此是线程安全的 使用的时候直接调用就行 不用再创建!
缺点:由于类加载的时候也把单例实例给初始化了,如果没有使用,就会造成资源的浪费!
单例模式之懒汉模式:
代码(Coding):
/** * 懒汉模式:指的不是类加载就开始创建,它是延迟加载的,指正在调用使用单例实例的时候才开始创建 */ public class SingleTonDemo02 { // 1、私有化构造器 private SingleTonDemo02(){} // 2、定义静态变量 懒汉模式的这个变量需要用volatile来修饰(原因的话后面再说) private static volatile SingleTonDemo02 singleTonDemo02 = null; // 3、公开获取INSTANCE(单例实例)的方法 public static SingleTonDemo02 getInstance() { // 先创建 要考虑高并发的情况 因此采用双重校验锁和volatile来保证线程安全 if (singleTonDemo02 == null) { // 第一次校验 // 上锁 synchronized (SingleTonDemo02.class) { if (singleTonDemo02 == null) { // 第二次校验 // 才开始创建 singleTonDemo02 = new SingleTonDemo02(); } } } return singleTonDemo02; } }
优点:懒汉模式是指延迟加载的模式,它不是类一创建就一并将单例实例初始化 而是在真正使用调用单例实例的时候 才开始初始化单例实例(这样就不会造成资源的浪费),它是通过双重校验锁和volatile来保证线程安全性的
单例模式之静态内部类:
代码(Coding):
/** * 静态内部类:既能保证线程的安全性 又能懒加载 因为它只有被调用的开始初始化静态内部类 因此是线程安全的 */ public class SingleTonDemo03 { // 1、私有化构造器 private SingleTonDemo03() { } // 2、静态内部类 private static class SingleTonHolder { // 定义静态变量 private static final SingleTonDemo03 INSTANCE = new SingleTonDemo03(); } // 3、提供获取单例实例的方法 public static final SingleTonDemo03 getInstance() { return SingleTonHolder.INSTANCE; } }
特点:静态内部类也是等单例实例被调用的时候才开始初始化,是线程安全的 并且是懒加载!
单例模式之枚举:
/** * 枚举:也是在第一次被调用的时候 才开始被JAVA虚拟机初始化 因此它是线程安全的 并且是懒加载的 */ public enum SingleTonDemo04 { INSTANCE; public SingleTonDemo04 getInstance() { return INSTANCE; } }
特点:枚举也是等单例模式被调用的时候 才被JAVA虚拟机初始化 也是线程安全的!并且它也是懒加载的!
总结:
单例模式适用于被经常访问的对象,或者创建和销毁时需要调用大量资源和时间,使用单例模式就可以避免频繁创建和销毁。单例模式的实现方式有四种:饿汉模式、懒汉模式、静态内部类、枚举
从代码简洁性、线程安全性和代码易读性综合来看,我个人比较推荐使用枚举和懒汉模式来实现单例模式(一般我们实际都是用懒汉模式)