设计模式(单例模式)

2020-11-06  本文已影响0人  Chenyangqi

1、饿汉式

可以通过静态变量和静态代码块两种方式实现,效果一样

public class Singleton1 {
   //方式1:通过静态变量方式创建
   private static final Singleton1 INSTANCE = new Singleton1();

   //方式2:通过静态代码块的方式,效果和方法1一样
//    private static final Singleton1 INSTANCE;
//
//    static {
//        INSTANCE = new Singleton1();
//    }

   /**
    * 私有的构造方法,防止产生多个对象
    */
   private Singleton1() {
   }

   /**
    * 通过该方法获得实例
    *
    * @return
    */
   public static Singleton1 getInstance() {
       return INSTANCE;
   }

   public void doSomething() {

   }
}

可通过如下方式,在多个线程中创建多个单例对象,查看创建的对象hashCode是否相同判断是否为单例

Executor executor = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    //测试饿汉式单例
                    Singleton1 singleton1 = Singleton1.getInstance();
                    Singleton1 singleton2 = Singleton1.getInstance();
                    System.out.println(singleton1.hashCode() + "\t-----\t" + singleton2.hashCode());
                }
            });
        }

打印结果如下,不同线程下的Singleton1对象都是同一个HashCode,表示是全局单例

2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061
2007961061  -----   2007961061

2、懒汉式-线程不安全

public class SingLeton2 {
   private static SingLeton2 INSTANCE;

   private SingLeton2() {
   }

   public static SingLeton2 getInstance() {
       if (INSTANCE == null) {
           INSTANCE = new SingLeton2();
       }
       return INSTANCE;
   }
}

多线程创建此单例hashcode如下,存在hashCode不一致的问题,所有没有做到全局单例

1337000531  -----   1337000531
1337000531  -----   1337000531
1337000531  -----   1337000531
1337000531  -----   1337000531
1337000531  -----   1337000531
1523178316  -----   1523178316
1337000531  -----   1337000531
1337000531  -----   1337000531
1337000531  -----   1337000531
1337000531  -----   1337000531

3、懒汉式 线程安全

public class Singleton3 {

   private static Singleton3 INSTANCE;

   private Singleton3() {
   }

   public static synchronized Singleton3 getINSTANCE() {
       if (INSTANCE == null) {
           INSTANCE = new Singleton3();
       }
       return INSTANCE;
   }
}

下面这种方式,虽然加锁了但是还是存在线程不安全的问题,同一时刻不同的线程走到if(instance==null)这一步时,还是会创建不同的对象

//方式二 线程不安全
   static class  Singleton7{
       private static Singleton7 instance;

       private Singleton7(){}

       public static Singleton7 getInstance() {
           if(instance==null){
               synchronized (Singleton7.class){
                   instance=new Singleton7();
               }
           }
           return instance;
       }
   }

4、双重检查

public class Singleton4 {
  private static volatile Singleton4 instance;

  private Singleton4() {
  }

  public static Singleton4 getInstance() {
      if (instance == null) {
          synchronized (Singleton4.class) {
              if (instance == null) {
                  instance = new Singleton4();
              }
          }
      }
      return instance;
  }
}

5、静态内部类

public class Singleton5 {
   private Singleton5() {
   }

   private static class Singleton5Instance {
       private static final Singleton5 INSTANCE = new Singleton5();
   }

   public static Singleton5 getInstance() {
       return Singleton5Instance.INSTANCE;
   }
}

6、枚举方式创建单例

public enum Singleton6 {
   INSTANCE;

   public void doSomething() {
       System.out.println("枚举创建");
   }

   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }
}
上一篇下一篇

猜你喜欢

热点阅读