1. 程式人生 > 其它 >java--JUC--單例模式

java--JUC--單例模式

  1. 餓漢式單例模式
    1. package com.model.danli;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/6/10 9:05
       */
      /**
       * 餓漢模式,即 上來就直接會建立一個物件
       *
       * 可能會浪費空間
       * */
      public class EHanDemo {
          
        //構造器私有
          private EHanDemo(){}
      
          private static final EHanDemo eHanDemo=new EHanDemo();
      
          public static EHanDemo getEHanDemo(){
              
      return eHanDemo; } }
  2. 懶漢式單例模式
    1.   
      package com.model.danli;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/6/10 9:17
       */
      
      /**
       * 懶漢式單例: 不是一上來就載入物件,而是等到我們需要的時候在建立
       *
       *
       *
       * */
      
      public class LazyMan {
      
          private LazyMan(){
              System.out.println(Thread.currentThread().getName()+"執行緒建立ok");
          }
          
      private static LazyMan lazyMan; //存在的問題:單執行緒下是有效的,但是當多執行緒時我們會造成多個物件的建立 public LazyMan getLazyMan(){ if (lazyMan==null){ lazyMan=new LazyMan(); } return lazyMan; } public static void main(String[] args) { LazyMan lazyMan=new LazyMan();
      for (int i = 0; i < 10; i++) { new Thread(() ->{ lazyMan.getLazyMan(); },String.valueOf(i)).start(); } } }
  3. 雙重檢測鎖模式的 懶漢式單例 DCL

    1. package com.model.danli;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/6/10 9:17
       */
      
      /**
       * 懶漢式單例: 不是一上來就載入物件,而是等到我們需要的時候在建立
       *
       *
       *
       * */
      
      public class LazyMan_DCL {
      
          private LazyMan_DCL(){
              System.out.println(Thread.currentThread().getName()+"執行緒建立例項ok");
          }
          private static volatile LazyMan_DCL lazyMan;
      
      
          //雙重檢測鎖模式,懶漢式單例,DCL單例
          public static LazyMan_DCL getLazyMan(){
              if (lazyMan==null){
                  synchronized(LazyMan_DCL.class){
                      if (lazyMan==null){
                          /*
                          * 不是原理性操作
                          * 底層的操作:
                          * 1.分配記憶體空間
                          * 2.執行構造方法,初始化物件
                          * 3.把這個物件指向這個空間
                          *
                          * 有可能會發生指令的重排--》解決方法 :使用 volatile修飾變數layMan
                          * */
                          lazyMan=new LazyMan_DCL();
                      }
                  }
              }
              return lazyMan;
          }
      
          public static void main(String[] args) {
              for (int i = 0; i < 10; i++) {
                  new Thread(() ->{
                     LazyMan_DCL.getLazyMan();
                  },String.valueOf(i)).start();
              }
          }
      }
  4. 反射機制可以破壞單例模式
    1. package com.model.danli;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/6/10 9:17
       */
      
      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;
      
      /**
       * 懶漢式單例: 不是一上來就載入物件,而是等到我們需要的時候在建立
       *
       *
       *
       * */
      
      public class LazyMan_DCL_FS {
      
          private LazyMan_DCL_FS(){
              System.out.println(Thread.currentThread().getName()+"執行緒建立例項ok");
          }
          private static volatile LazyMan_DCL_FS lazyMan;
      
      
          //雙重檢測鎖模式,懶漢式單例,DCL單例
          public static LazyMan_DCL_FS getLazyMan(){
              if (lazyMan==null){
                  synchronized(LazyMan_DCL_FS.class){
                      if (lazyMan==null){
                          /*
                          * 不是原理性操作
                          * 底層的操作:
                          * 1.分配記憶體空間
                          * 2.執行構造方法,初始化物件
                          * 3.把這個物件指向這個空間
                          *
                          * 有可能會發生指令的重排--》解決方法 :使用 volatile修飾變數layMan
                          * */
                          lazyMan=new LazyMan_DCL_FS();
                      }
                  }
              }
              return lazyMan;
          }
      
          public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
             /* for (int i = 0; i < 10; i++) {
                  new Thread(() ->{
                     LazyMan_DCL.getLazyMan();
                  },String.valueOf(i)).start();
              }*/
      
              //反射機制,能破壞單例模式:那我們呢如何解決呢?
              Constructor<LazyMan_DCL_FS> dclConstructor= LazyMan_DCL_FS.class.getDeclaredConstructor(null);
              dclConstructor.setAccessible(true);
              LazyMan_DCL_FS instance=dclConstructor.newInstance();
              LazyMan_DCL_FS instance2=dclConstructor.newInstance();
              System.out.println(instance);
              System.out.println(instance2);
          }
      }
  5. 解決反射機制的對單例模式的破壞:反射不能破壞enum的單例
    1. package com.model.danli;
      
      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;
      
      /**
       * @Description:測試類
       * @Author: 張紫韓
       * @Crete 2021/6/10 13:30
       */
      public enum EnumDemo {
          INSTANCE;
          public EnumDemo getInstance(){
              return INSTANCE;
          }
      
      }
      class Test{
          public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
              EnumDemo enumDemo=EnumDemo.INSTANCE;
              Constructor<EnumDemo> demoConstructor=EnumDemo.class.getDeclaredConstructor(String.class,int.class);
              demoConstructor.setAccessible(true);
              EnumDemo enumDemo1=demoConstructor.newInstance();
              System.out.println(enumDemo);
              System.out.println(enumDemo1);
          }
      }
    2.