单例模式
单例模式(Singleton Pattern)是 Java 中较为简单且源码中常出现的设计模式,属于创建型模式。
实现一个类只有一个实例化对象用来提供全局对象场景例如SpringIoc的单例。
单例的五种写法有懒汉式、饿汉式、双重检验锁、枚举、静态内部类。
假如不想一个类频繁创建销毁可以使用到单例。
1、懒汉式
首先这个写法在单线程时候式安全的,多线程的时候就不安全了。
package com.mode.singleton;
public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
测试类
首先我们循环遍历创建线程去获取类对象
package com.mode.singleton;
public class TestSingleton {
public static void main(String[] args) {
for(int i=0;i<10;i++){
new Thread(()->{
System.out.println(Singleton.getInstance());;
}).start();
}
// System.out.println(Singleton.getInstance());
// System.out.println(Singleton.getInstance());
}
}
结果
从结果中可以看出哈多线程情况下会出现多例。
假如一次执行没有出现多例可以多执行几便哈,或者在if判断后加个sleep。
懒汉式(安全)
在方法上加上synchronized锁就行了。
但是效率可想而之肯定式慢的。
package com.mode.singleton;
public class Singleton {
private static Singleton singleton;
private Singleton (){}
public synchronized static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
2、饿汉式
类加载时就初始化 假如没有地方使用是占用资源的,饿汉式是线程安全的
package com.mode.singleton;
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
3、双重校验锁
这种方式采用双锁机制,安全且在多线程情况下能保持高性能
package com.mode.singleton;
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
4、静态内部类
在静态内部类里创建单例,在装载该内部类时才会去创建单例
线程安全:类是由 JVM加载所以只会加载一次
package com.mode.singleton;
public class Singleton {
//内部类
private static class Singleton2 {
private static final Singleton singleton = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return Singleton2.singleton;
}
}
5、枚举
反序列化和反射可以破解单例,而枚举不能被破坏。
package com.mode.singleton;
public enum SingletonEnum {
INSTANCE;
}