Java中的单例模式是一种设计模式,它用于控制类的实例化过程,确保在整个应用程序中,一个类只有一个实例存在。这在处理全局资源、缓存、线程池等场景时非常有用,因为它可以避免多个实例之间的数据冲突,节省系统资源。
在最简单的单例模式实现中,通常采用"饿汉式",即在类加载时就创建单例实例,代码如下:
```java
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
```
这种实现方式线程安全,但由于类加载时就创建实例,可能导致资源浪费,即使实例从未被使用。
另一种常见实现是"懒汉式",延迟实例化,只在首次需要时创建实例,但原始的懒汉式实现不线程安全:
```java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
```
为了使懒汉式实现线程安全,可以使用同步锁,即在`getInstance()`方法上添加`synchronized`关键字:
```java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
```
然而,这种方式虽然保证了线程安全,但每次调用`getInstance()`都会同步,降低了效率。
为了解决这个问题,可以使用双检锁/双重校验锁(DCL,即Double-Check Locking)来优化:
```java
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;
}
}
```
在这个版本中,只有在`instance`为null且需要创建实例时才会进行同步,提高了效率。`volatile`关键字用于确保多线程环境下的可见性和有序性,保证了实例的正确创建。
另外,还可以使用静态内部类的方式实现单例,这种方式既能保证线程安全,又实现了延迟初始化:
```java
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
```
静态内部类在外部类被加载时并不会立即加载,而是只有在调用`getInstance()`时才加载,从而实现了延迟初始化。
Java中的单例模式有多种实现方式,包括饿汉式、懒汉式、同步锁、双检锁和静态内部类等。选择哪种实现取决于对线程安全、性能和延迟初始化的需求。在实际应用中,应根据具体场景选择合适的单例模式实现。