单例的四种实现方式

饿汉式

package com.personal.newoffer;

/**
 * Created by zhouxiang on 2018/10/11.
 * 单例 饿汉式
 * 优点:简单,没有多线程问题
 * 缺点:ru'gu浪费空间,占用资源,如果一直不调用getIntance,那么创建的对象就是浪费了,
 */

public class Singleton1 {

  //只有类第一次加载时才会调用
  private static Singleton1 mInstance = new Singleton1();

  public static Singleton1 getInstance() {
    return mInstance;
  }
}

懒汉式

package com.personal.newoffer;

import java.io.Serializable;

/**
 * Created by zhouxiang on 2018/10/11.
 * 饿汉式+双重判断
 * 第1个判空是为了防止每次都执行synchronized,提升效率
 * 第2个判空是为了防止多个线程同时进入了第1个判空里会导致创建了多个对象
 * 优点:双重判空既防止了多线程问题又不会影响效率
 * 缺点:clone和反射以及序列化都会破解这种单例实现方式
 */

public class Singleton2 implements Serializable {
  private static Singleton2 mInstance;
  private static boolean flag = false;


  /**
   * 防止被反射
   */
  private Singleton2() {
    if (!flag) {
      flag = true;
    } else {
      try {
        throw new Exception("已经创建过一个对象了");
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

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


  /**
   * 重新clone方法,防止被clone获取新的对象
   * 
   * @return
   * @throws CloneNotSupportedException
   */
  @Override
  protected Object clone() throws CloneNotSupportedException {
    return getInstance();
  }

  /**
   * 下面通过序列化、反序列化就会导致创建新的对象
   * ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
   * oos.writeObject(Singleton2.getInstance());
   * File file = new File("tempFile");
   * ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
   * Singleton2 singleton2 = (Singleton2)ois.readObject();
   */
  // 这个就是为了防止反序列化(readObject)时获取到新的对象
  private Object readResolve() {
    return mInstance;
  }

  public void test() {
    System.out.println("test");
  }
}

内部类

package com.personal.newoffer;

/**
 * Created by zhouxiang on 2018/10/11.
 * 优点:既防止了多线程问题又解决了可能占用资源的问题
 * 缺点:clone、反射、序列化都能破解
 */

public class Singleton3 {

  private static class InnerClass {
    private static Singleton3 mInstance = new Singleton3();
  }

  public Singleton3 getInstance() {
    return InnerClass.mInstance;
  }
}

枚举

package com.personal.newoffer;

/**
 * Created by zhouxiang on 2018/10/11.
 * 枚举才是无敌的,为什么是无敌的?
 * 1.简单
 * 2.不能被反射以及反序列化攻击(jvm保证了这两点)
 */

public enum Singleton4 {
  INSTANCE;
}

你可能感兴趣的:(单例的四种实现方式)