一)饿汉模式(线程安全)
/** * 单例模式<br/> * 一)饿汉式,线程安全<br/> * @author me@longlonggo.com * 创建日期:2018年9月16日 <br/> */ public class Singleton1 { //优点:声明的时候就已经初始化Singleton1,确保了对象的唯一性 //缺点:声明的时候就初始化对象会浪费不必要的资源 //如何保证线程安全:类初始化只有一次,所以类创建的对象只会有一个 private static Singleton1 singletonObj = new Singleton1(); //构造函数要定义为私有的,避免错误执行实例化 private Singleton1() {} //返回单例对象 public Singleton1 getSingleton1() { return singletonObj; } }
二)懒汉模式(非线程安全)
/** * 单例模式<br/> * 二)懒汉式,非线程安全<br/> * @author me@longlonggo.com * 创建日期:2018年9月16日 <br/> */ public class Singleton2 { //优点:精确控制单例初始化时间,充分利用延迟加载,只会在调用时才被初始化, //缺点:为防止对象被多次加载,使用synchronized进行同步,并发环境可能会降低性能 private static Singleton2 singletonObj; //构造函数要定义为私有的,避免错误执行实例化 private Singleton2() {} //返回单例对象 public static synchronized Singleton2 getSingleton2() { if(singletonObj == null) { singletonObj = new Singleton2(); } return singletonObj; } }
三)内部类实现(线程安全)
/** * 单例模式<br/> * 三)内部类,线程安全<br/> * @author me@longlonggo.com * 创建日期:2018年9月16日 <br/> */ public class Singleton3 { //构造函数要定义为私有的,避免错误执行实例化 private Singleton3() {} //优点: //1、没有使用并发锁,高并发环境下性能高 //2、只有getSingleton2()被使用时,实例才会创建(巧妙使用了类和内部类的初始化加载方式) //3、内部类被声明为私有的,外部不能访问,只能通过getSingleton2()执行初始化,利用jvm的类初始化机制创建单例 private static class SingletonHolder{ private static final Singleton3 singletonObj = new Singleton3(); } //返回单例对象 public static Singleton3 getSingleton2() { return SingletonHolder.singletonObj; } }
四)双重检查(线程安全)
/** * 单例模式<br/> * 四)双重检查,线程安全<br/> * @author me@longlonggo.com * 创建日期:2018年9月16日 <br/> */ public class Singleton4 { private static Singleton4 singletonObj; //构造函数要定义为私有的,避免错误执行实例化 private Singleton4() {} //优点:资源利用率高,效率高 //缺点:第一次加载时比较慢;在JDK1.4之前版本中,java处理器运行乱序执行,所以可能出现失败 //详参考:https://blog.csdn.net/anjxue/article/details/51038466 //两次判空: //1) 第一次判断,提高性能,避免不必要的同步锁操作(synchronized也是消耗性能的) //2) 第二次判断,解决多线程下安全问题: // 2.1)多个线程同时到达【位置2】 // 2.2)一线程先执行【位置3】中的代码,并在此时创建单例对象 // 2.3)一线程执行完后,二线程执行到【位置3】,由于单例对象已经一线程中被创建,所以直接跳出 public static Singleton4 getSingleton2() { if(singletonObj == null) { //位置2 synchronized (Singleton4.class) { //位置3 if(singletonObj == null) { singletonObj = new Singleton4(); } } } return singletonObj; } }