• 设计模式__单例模式的八种写法


    单例模式是非常常用的设计模式,不论是在无意用到还是有意为之,运用到的情况是很多的。本篇博客作为学习笔记,记录一下八种应用单例模式的方法:

    1. package com.DesignMode.Singleton;
    2. /**
    3. * 饿汉式
    4. * 类加载到内存后,就实例化一个单例,JVM保证线程安全
    5. * 简单实用,推荐使用
    6. * 扩展:不实例化时,经常会用到反射Class.forName(类名)
    7. * 唯一缺点:不管用到与否,类加载时就会完成实例化
    8. */
    9. public class Mgr01 {
    10. private static final Mgr01 INSTANCE = new Mgr01();
    11. private Mgr01() {
    12. }
    13. public static Mgr01 getInstance() {
    14. return INSTANCE;
    15. }
    16. public void m() {
    17. System.out.println("m");
    18. }
    19. public static void main(String[] args, Mgr01 m21) {
    20. Mgr01 m1 = Mgr01.getInstance();
    21. Mgr01 m2 = Mgr01.getInstance();
    22. System.out.println(m1 == m2);
    23. }
    24. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. * 本质上与01一致
    4. */
    5. public class Mgr02 {
    6. private static final Mgr02 INSTANCE;
    7. static {
    8. INSTANCE = new Mgr02();
    9. }
    10. private Mgr02(){}
    11. public static Mgr02 getInstance(){
    12. return INSTANCE;
    13. }
    14. public void m() {
    15. System.out.println("m");
    16. }
    17. public static void main(String[] args, Mgr01 m21) {
    18. Mgr01 m1 = Mgr01.getInstance();
    19. Mgr01 m2 = Mgr01.getInstance();
    20. System.out.println(m1 == m2);
    21. }
    22. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. * Lazy Loading
    4. * 懒汉式
    5. * 虽然达到了按需初始化的目的,但也带来了线程不安全的问题
    6. */
    7. public class Mgr03 {
    8. private static Mgr03 INSTANCE;
    9. private Mgr03() {
    10. }
    11. public static Mgr03 getInstance() {
    12. if (INSTANCE == null) {
    13. try {
    14. Thread.sleep(1);
    15. } catch (Exception e) {
    16. e.printStackTrace();
    17. }
    18. INSTANCE = new Mgr03();
    19. }
    20. return INSTANCE;
    21. }
    22. public void m() {
    23. System.out.println("m");
    24. }
    25. public static void main(String[] args) {
    26. for (int i = 0; i < 100; i++) {
    27. /*new Thread(new Runnable() {
    28. //Runnable针对的是只有一个匿名内部类的接口
    29. @Override
    30. public void run() {
    31. ...
    32. }
    33. }).start();*/
    34. new Thread(new Runnable() {
    35. public void run() {
    36. System.out.println(Mgr03.getInstance().hashCode());
    37. }
    38. }).start();
    39. }
    40. }
    41. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. * Lazy Loading
    4. * 懒汉式
    5. * 虽然达到了按需初始化的目的,但也带来了线程不安全的问题
    6. * 可以通过synchronized锁定对象解决,但也带来效率下降的问题,此处锁定的是Manager04.Class对象
    7. */
    8. public class Mgr04 {
    9. private static Mgr04 INSTANCE;
    10. private Mgr04() {
    11. }
    12. public static synchronized Mgr04 getInstance() {
    13. if (INSTANCE == null) {
    14. try {
    15. Thread.sleep(1);
    16. } catch (Exception e) {
    17. e.printStackTrace();
    18. }
    19. INSTANCE = new Mgr04();
    20. }
    21. return INSTANCE;
    22. }
    23. public void m() {
    24. System.out.println("m");
    25. }
    26. public static void main(String[] args) {
    27. for (int i = 0; i < 100; i++) {
    28. /*new Thread(new Runnable() {
    29. //Runnable针对的是只有一个匿名内部类的接口
    30. @Override
    31. public void run() {
    32. ...
    33. }
    34. }).start();*/
    35. new Thread(new Runnable() {
    36. public void run() {
    37. System.out.println(Mgr04.getInstance().hashCode());
    38. }
    39. }).start();
    40. }
    41. }
    42. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. * Lazy Loading
    4. * 懒汉式
    5. * 虽然达到了按需初始化的目的,但也带来了线程不安全的问题
    6. * 可以通过synchronized锁定对象解决,但也带来效率下降的问题,此处锁定的是Manager04.Class对象
    7. */
    8. public class Mgr05 {
    9. private static Mgr05 INSTANCE;
    10. private Mgr05() {
    11. }
    12. public static Mgr05 getInstance() {
    13. if (INSTANCE == null) {
    14. //妄图通过减小同步代码块的方式提高效率,但不可行
    15. synchronized (Mgr05.class) {
    16. try {
    17. Thread.sleep(1);
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. }
    21. INSTANCE = new Mgr05();
    22. }
    23. }
    24. return INSTANCE;
    25. }
    26. public void m() {
    27. System.out.println("m");
    28. }
    29. public static void main(String[] args) {
    30. for (int i = 0; i < 100; i++) {
    31. /*new Thread(new Runnable() {
    32. //Runnable针对的是只有一个匿名内部类的接口
    33. @Override
    34. public void run() {
    35. ...
    36. }
    37. }).start();*/
    38. /*new Thread(() -> {
    39. System.out.println(Mgr05.getInstance().hashCode());
    40. }).start();*/
    41. }
    42. }
    43. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. * Lazy Loading
    4. * 懒汉式
    5. * 虽然达到了按需初始化的目的,但也带来了线程不安全的问题
    6. * 可以通过synchronized锁定对象解决,但也带来效率下降的问题,此处锁定的是Manager04.Class对象
    7. */
    8. public class Mgr06 {
    9. private static volatile Mgr06 INSTANCE;
    10. //JIT编译时会变成本地语言,此处可能会没有初始化INSTANCE就返回值;这里的操作不是原子性操作
    11. private Mgr06() {
    12. }
    13. public static Mgr06 getInstance() {
    14. if (INSTANCE == null) {
    15. //INSTANCE为空 上锁
    16. synchronized (Mgr06.class) {
    17. //双重检测锁 DCL懒汉式
    18. if (INSTANCE == null) {
    19. try {
    20. Thread.sleep(1);
    21. } catch (Exception e) {
    22. e.printStackTrace();
    23. }
    24. INSTANCE = new Mgr06();
    25. }
    26. }
    27. }
    28. return INSTANCE;
    29. }
    30. public void m() {
    31. System.out.println("m");
    32. }
    33. public static void main(String[] args) {
    34. for (int i = 0; i < 100; i++) {
    35. /*new Thread(new Runnable() {
    36. //Runnable针对的是只有一个匿名内部类的接口
    37. @Override
    38. public void run() {
    39. ...
    40. }
    41. }).start();*/
    42. /* new Thread(() -> {
    43. System.out.println(Mgr06.getInstance().hashCode());
    44. }).start();*/
    45. }
    46. }
    47. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. *静态内部类方式
    4. * JVM保证单例
    5. * 加载外部类时不会加载内部类,实现懒加载
    6. */
    7. public class Mgr07 {
    8. private static Mgr07 INSTANCE;
    9. private Mgr07() {
    10. }
    11. private static class Mgr07Holder {
    12. private final static Mgr07 INSTANCE = new Mgr07();
    13. }
    14. public static Mgr07 getInstance() {
    15. return Mgr07Holder.INSTANCE;
    16. }
    17. public void m() {
    18. System.out.println("m");
    19. }
    20. public static void main(String[] args) {
    21. for (int i = 0; i < 100; i++) {
    22. /*new Thread(new Runnable() {
    23. //Runnable针对的是只有一个匿名内部类的接口
    24. @Override
    25. public void run() {
    26. ...
    27. }
    28. }).start();*/
    29. /*new Thread(() -> {
    30. System.out.println(Mgr07.getInstance().hashCode());
    31. }).start();*/
    32. }
    33. }
    34. }
    1. package com.DesignMode.Singleton;
    2. /**
    3. *不仅可以解决线程同步,还可以防止反序列化
    4. *
    5. * 枚举类没有构造方法
    6. */
    7. public enum Mgr08 {
    8. INSTANCE;
    9. public void m() {
    10. System.out.println("m");
    11. }
    12. public static void main(String[] args) {
    13. for (int i = 0; i < 100; i++) {
    14. /*new Thread(new Runnable() {
    15. //Runnable针对的是只有一个匿名内部类的接口
    16. @Override
    17. public void run() {
    18. ...
    19. }
    20. }).start();*/
    21. /*new Thread(() -> {
    22. System.out.println(Mgr08.INSTANCE.hashCode());
    23. }).start();*/
    24. }
    25. }
    26. }

    实际的联系与应用中,还是要考虑到自己会用什么,理解哪种方式,哪种方式对自己的代码优化程度更高选定,玩的花不如写的实~

  • 相关阅读:
    Mybatis( If条件失效 )
    Win11打印机文档被挂起如何解决?
    融云「百幄」之视频会议和直播,让办公桌无限延伸
    Java-集合
    PEG化四氧化三铁纳米颗粒(氨基末端)NH2-PEG-Fe3O4
    R语言根据日历周期处理时间序列数据(周、月、年等):使用xts包的apply.monthly函数和mean函数计算时间序列的月平均值(monthly)
    LeetCode199. Binary Tree Right Side View
    一个rar压缩包如何分成三个?
    数字孪生助力轨道交通安保可视化应用
    vue全局事件总线
  • 原文地址:https://blog.csdn.net/weixin_46813221/article/details/126341253