设计模式当中的单例模式想必是大家耳熟能详的了,或多或少都有些了解,但未必了解的全,在这里我总结了一共7种单例模式,仅供大家参考。
饿汉式
类加载到内存后,就实例化一个单例,JVM保证线程安全
简单实用,推荐使用
唯一缺点:不管用到与否,类加载时就完成实例化
main方法是为了测试类是否是单例
/**
* @author baskbull
* @date 2021/5/18 13:40
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单实用,推荐使用
* 唯一缺点:不管用到与否,类加载时就完成实例化
*/
public class Singleton1 {
//只会初始化一次
private static final Singleton1 INSTANCE = new Singleton1();
private Singleton1() {
}
public static Singleton1 getInstance() {
return INSTANCE;
}
public static void main(String[] args) {
Singleton1 singleton1 = Singleton1.getInstance();
Singleton1 singleton2 = Singleton1.getInstance();
//true
System.out.println(singleton1 == singleton2);
}
}
饿汉式(静态代码块)
/**
* @author baskbull
* @date 2021/5/18 13:45
* 本质上和1没区别
*/
private static final Singleton2 INSTANCE;
//只会初始化一次
static {
INSTANCE = new Singleton2();
}
private Singleton2() {
}
public static Singleton2 getInstance() {
return INSTANCE;
}
public static void main(String[] args) {
Singleton2 singleton1 = Singleton2.getInstance();
Singleton2 singleton2 = Singleton2.getInstance();
//true
System.out.println(singleton1 == singleton2);
}
懒汉式
lazy loading
懒汉式
虽然达到了按需初始化的目的,但却带来线程不安全的问题
/**
* @author baskbull
* @date 2021/5/18 18:59
* lazy loading
* 懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
*/
public class Singleton3 {
private static Singleton3 INSTANCE;
private Singleton3(){}
private static Singleton3 getInstance(){
if(INSTANCE == null){
INSTANCE = new Singleton3();
}
return INSTANCE;
}
}
懒汉式(加锁解决线程不安全问题)
lazy loading
懒汉式
虽然达到了按需初始化的目的,但却带来线程不安全的问题
可以通过synchronized解决,但也带来效率下降
/**
* @author baskbull
* @date 2021/5/18 18:59
* lazy loading
* 懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
* 可以通过synchronized解决,但也带来效率下降
*/
public class Singleton4 {
private static Singleton4 INSTANCE;
private Singleton4(){}
private static synchronized Singleton4 getInstance(){
if(INSTANCE == null){
INSTANCE = new Singleton4();
}
return INSTANCE;
}
}
饿汉式(不可行,原因在main函数中)
/**
* @author baskbull
* @date 2021/5/18 18:59
* lazy loading
* 懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
* 可以通过synchronized解决,但也带来效率下降
*/
public class Singleton5 {
private static Singleton5 INSTANCE;
private Singleton5(){}
private static Singleton5 getInstance(){
if(INSTANCE == null){
//尝试通过减小同步代码块的方式来提高效率,不可行
synchronized (Singleton5.class){
INSTANCE = new Singleton5();
}
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
System.out.println(Singleton5.getInstance().hashCode());
}).start();
}
}
}
双重校验锁实现单例
/**
* @author baskbull
* @date 2021/5/18 18:59
* lazy loading
* 懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
* 可以通过synchronized解决,但也带来效率下降
*/
public class Singleton6双重校验 {
private static volatile Singleton6双重校验 INSTANCE;
private Singleton6双重校验() {
}
private static Singleton6双重校验 getInstance() {
//双重检查
if (INSTANCE == null) {
synchronized (Singleton6双重校验.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton6双重校验();
}
}
}
return INSTANCE;
}
}
静态内部类实现单例
静态内部类方式
jvm保证单例
加载外部类时不会加载内部类,这样可以实现懒加载
/**
* @author baskbull
* @date 2021/5/18 18:59
* 静态内部类方式
* jvm保证单例
* 加载外部类时不会加载内部类,这样可以实现懒加载
*/
public class Singleton7静态内部类 {
private Singleton7静态内部类() {
}
private static class Singleton7Holder{
private final static Singleton7静态内部类 INSTANCE = new Singleton7静态内部类();
}
private static Singleton7静态内部类 getInstance(){
return Singleton7Holder.INSTANCE;
}
}
枚举
在大家为单例的实现争论不休的时候,Java的创始人在《Effective Java》中推荐使用枚举来实现单例
不仅可以解决线程同步,还可以解决反序列化
枚举类没有构造方法
这个虽然看着别扭,但就是这么简单~
/**
* @author baskbull
* @date 2021/5/18 18:59
* 不仅可以解决线程同步,还可以解决反序列化
* 枚举类没有构造方法
*/
public enum Singleton8枚举 {
INSTANCE;
}
好了,单例模式就到这里,下一篇来讲策略模式
438

被折叠的 条评论
为什么被折叠?



