1. 单例模式测试类SingletonTest
package com.zhaoshuangjian.mode01_单例模式; import com.zhaoshuangjian.mode01_单例模式.mode01.Singleton1; import com.zhaoshuangjian.mode01_单例模式.mode01.Singleton2; import com.zhaoshuangjian.mode01_单例模式.mode01.Singleton3; import com.zhaoshuangjian.mode01_单例模式.mode01.Singleton4; /** * SingletonTest 手写代码实现单例模式 * * @Auther: zhaoshuangjian 2023-03-23 下午1:07 */ public class SingletonTest { public static void main(String[] args) { // 1、单例模式 -- 非线程安全 Singleton1 singleton1 = Singleton1.getInstance(); singleton1.show(); System.out.println("==================分割线=================="); // 2、单例模式 -- 线程安全,每次获取对象,都对当前的对象加锁 Singleton2 singleton2 = Singleton2.getInstance(); singleton2.show(); System.out.println("==================分割线=================="); // 3、单例模式 -- 线程安全,只在第一次创建实例对象的时候加锁(推荐) Singleton3 singleton3 = Singleton3.getInstance(); singleton3.show(); System.out.println("==================分割线=================="); // 4、单例模式 -- 内部静态工厂类提前创建好实例,JVM保证instance只创建一次,且线程安全(推荐) Singleton4 singleton4 = Singleton4.getInstance(); singleton4.show(); /** * 以上四种单例模式,没有一种是十全十美的 * 就拿最后一种来说,通过内部类机制达到了线程安全且实例只被创建一次,这些都是JVM帮我们实现的,我们无需关心 * 但是,如果内部类自己的构造函数出现了问题,而不是在创建instance实例的时候出现了问题 * 这时候,我们试想一下,我们外部还能顺利拿到单例对象吗?答案是肯定不行 * 虽然这无疑会增加一道风险,但是相比我们手动加同步块来说,要好的多了 */ } }
2. Singleton1 单例模式-非线程安全
package com.zhaoshuangjian.mode01_单例模式.mode01; /** * Singleton1 单例模式-非线程安全 * * @Auther: zhaoshuangjian 2023-03-23 下午1:09 */ public class Singleton1 { // 私有构造器,防止外部new实例 private Singleton1(){} private static Singleton1 instance = null; /** * 非线程安全,多线程下会有问题【多线程抢资源,谁先抢到呢?会不会出现N个线程拿到的实例不是同一个呢?】 * @return */ public static Singleton1 getInstance() { if (instance == null) { instance = new Singleton1(); } return instance; } public void show(){ System.out.println("你好,我是单例模式一!"); } }
3. Singleton2 单例模式-线程安全(对当前单例对象上锁)
package com.zhaoshuangjian.mode01_单例模式.mode01; /** * Singleton2 单例模式-线程安全(对当前单例对象上锁) * * @Auther: zhaoshuangjian 2023-03-23 下午1:12 */ public class Singleton2 { // 私有构造器,防止外部new实例 private Singleton2(){} private static Singleton2 instance = null; /** * 虽然线程安全,但是每次调用getInstance获得实例的时候,都会对当前的对象进行加锁 * 注意,是每一次,这样的话多线程环境下性能会有所下降,但是我们知道单例模式的实例是全局只创建一次的 * 因此,这个锁不应该在每次获取实例的时候加锁,而应该加在第一次创建对象上 * @return */ public static synchronized Singleton2 getInstance() { if (instance == null) { instance = new Singleton2(); } return instance; } public void show(){ System.out.println("你好,我是单例模式二!"); } }
4.Singleton3 单例模式-线程安全(只在第一次创建实例的时候加锁)
package com.zhaoshuangjian.mode01_单例模式.mode01; /** * Singleton3 单例模式-线程安全(只在第一次创建实例的时候加锁) * * @Auther: zhaoshuangjian 2023-03-23 下午1:14 */ public class Singleton3 { // 私有构造器,防止外部new实例 private Singleton3(){} private static Singleton3 instance = null; /** * 区别于Singleton2,注意synchronized关键字【同步块】的位置 * @return */ public static Singleton3 getInstance() { if (instance == null) { synchronized (Singleton3.class){ if(instance == null){ instance = new Singleton3(); } } } return instance; } public void show(){ System.out.println("你好,我是单例模式三!"); } }
5.Singleton4 单例模式-内部静态工厂类提前创建好实例对象
package com.zhaoshuangjian.mode01_单例模式.mode01; /** * Singleton4 单例模式-内部静态工厂类提前创建好实例对象 * * @Auther: zhaoshuangjian 2023-03-23 下午1:15 */ public class Singleton4 { // 私有构造器,防止外部new实例 private Singleton4(){} private static class SingletonFactory{ private static Singleton4 instance = new Singleton4(); } public static Singleton4 getInstance(){ return SingletonFactory.instance; } public void show(){ System.out.println("你好,我是单例模式四!"); } }