设计模式·单例模式

1、饿汉式

  • 优点:类加载的时候完成实例化,避免了线程同步问题
  • 缺点:在类加载的时候就完成实例化,没有达到Lazy Loading的效果,如果该类未使用则造成了内存浪费

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

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、枚举方式创建单例

  • <<Effective Java>>推荐使用这种方式创建单例,项目中推荐使用
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;
   }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。