Java开发中,常常使用单例模式减少代码开销,单例模式有哪四种常见的写法?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在Java开发中,单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。尽管您提到了四种常见的写法,但实际上,主要讨论的通常有三种基本实现方式和一种线程安全的懒汉式变体,共计四种。以下是这四种写法的简要说明:
饿汉式(静态常量): 这是最简单直接的方式,通过静态初始化块或直接声明静态final变量来创建单例实例。这种方式在类加载时就完成了实例化,保证了线程安全,但可能会造成资源浪费,如果这个单例从未被使用过。
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
饿汉式(静态代码块): 与第一种类似,也是在类加载时完成实例化,只是实例化的逻辑放在了静态代码块中,适用于更复杂的初始化操作。
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
懒汉式(线程不安全): 实例在第一次调用getInstance()
方法时才被创建,但是这种原始的懒汉式写法在多线程环境下是不安全的。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
懒汉式(线程安全,同步方法): 为了解决多线程问题,可以在getInstance()
方法上加锁,这样虽然保证了线程安全,但是每次调用都会进行同步检查,影响性能。
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重检查锁定(DCL, Double-Checked Locking): 这是第四种常见写法,结合了懒汉式和线程安全的需求,同时减少了同步带来的性能开销。这是目前推荐的单例实现方式之一。
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
请注意,从Java 5开始,由于JVM内存模型的改进,双重检查锁定模式已经成为实现线程安全懒汉式单例的有效且高效的方法,特别是通过使用volatile
关键字确保了实例初始化的可见性。