1、代码实现
1.1 饿汉式-1
静态变量方式
public class Singleton {
private static Singleton singleton = new Singleton();
/**
* 私有构造方法
*/
private Singleton() {}
public static Singleton getInstance() {
return singleton;
}
}
1.2 饿汉式-2
静态代码块方式
public class Singleton {
private static Singleton singleton;
private Singleton() {}
static {
singleton = new Singleton();
}
public static Singleton getInstance() {
return singleton;
}
}
1.3 饿汉式-3
枚举方式
public enum Singleton {
SINGLETON
}
1.4 懒汉式-1
线程不安全
public class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
1.5 懒汉式-2
线程安全-1
public class Singleton {
private static Singleton singleton = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
1.6 懒汉式-3
线程安全-2
public class Singleton {
/**
* volatile:禁止指令重排
*/
private static volatile Singleton singleton;
/**
* 构造方法私有
*/
private Singleton() {}
/**
* DCL(Double Check Lock)双重校验锁
*/
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
/**
* 对象初始化过程:
* 1 分配对象内存空间
* 2 初始化对象
* 3 指向刚刚分配的内存空间
* 因为 步骤 2 和 步骤 3 没有数据依赖
* 有可能会出现指令重排
* 2 和 3 步骤对调,会导致对象还没有初始化成功
* 取出来的时候对象为 null
*/
singleton = new Singleton();
}
}
}
return singleton;
}
}
1.7 懒汉式-4
静态内部类方式
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
}
}
2、破坏单例模式
2.1 序列化方式
以静态内部类为例
public class Singleton implements Serializable {
private Singleton() {}
private static class SingletonHolder {
private final static Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
}
}
测试类:
public class Client {
public static void main(String[] args) throws Exception {
writeObject();
readObject();
readObject();
}
/**
* 从文件中读取对象
*/
public static void readObject() throws Exception {
ObjectInputStream objectInputStream =
new ObjectInputStream(new FileInputStream("D:/桌面/1.txt"));
Singleton singleton = (Singleton) objectInputStream.readObject();
System.out.println(singleton);
objectInputStream.close();
}
/**
* 将对象写入到文件中
*/
public static void writeObject() throws Exception {
Singleton instance = Singleton.getInstance();
ObjectOutputStream objectOutputStream =
new ObjectOutputStream(new FileOutputStream("D:/桌面/1.txt"));
objectOutputStream.writeObject(instance);
objectOutputStream.close();
}
}
运行结果:
2.2 反射方式
以静态内部类为例
public class Singleton implements Serializable {
private Singleton() {}
private static class SingletonHolder {
private final static Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
}
}
测试类:
public class Client2 {
public static void main(String[] args) throws Exception {
// 获取 class 对象
Class<Singleton> singletonClass = Singleton.class;
// 获取无参构造方法
Constructor<Singleton> constructor = singletonClass.getDeclaredConstructor();
// 取消访问检查
constructor.setAccessible(true);
// 创建两个对象
Singleton singleton1 = constructor.newInstance();
Singleton singleton2 = constructor.newInstance();
System.out.println(singleton1 == singleton2);
}
}
运行结果:
3、解决单例模式被破坏
3.1 序列化方式
添加 readResolve()
方法
public class Singleton implements Serializable {
private Singleton() {}
private static class SingletonHolder {
private final static Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
}
/**
* 进行反序列化时,会自动调用该方法,将该方法的返回值直接返回
*/
public Object readResolve() {
return SingletonHolder.SINGLETON;
}
}
3.2 反射方式
通过标志位
public class Singleton implements Serializable {
/**
* 标志位
*/
private static boolean flag = false;
private Singleton() {
/**
* 加锁是为了线程安全
*/
synchronized (Singleton.class) {
if (flag == true) {
throw new RuntimeException("不要试图利用反射破坏单例");
}
flag = true;
}
}
private static class SingletonHolder {
private final static Singleton SINGLETON = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
}
}