Java多线程实战之单例模式与多线程的实例详解
什么是单例模式?
单例模式是一种对象创建型设计模式,用于保证一个类只有一个实例,并提供一个全局访问点。
在单例模式中,一个类只有一个实例化对象,如果再次实例化,将返回同一对象的引用。这种设计模式也有助于实现对资源的共享和对系统的配置进行集中化管理。
单例模式的实现
我们可以使用如下的方法来实现单例模式:
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在上述的实现中,getInstance() 方法使用了 "懒汉式" 的方式,在需要时才创建 Singleton 对象。这种方式在单线程环境中表现良好,但在多线程环境中可能会出现问题。
多线程环境下的单例模式
当多个线程同时访问 Singleton 类的 getInstance() 方法时,可能创建出多个 Singleton 对象,因此需要在该方法中添加同步锁。
我们可以采用如下方式来实现:
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在上述实现中,getInstance() 方法使用了 synchronized 关键字,确保只有一个线程能够访问该方法。但这种实现方式在多线程环境中会降低程序的性能。
双重校验锁实现多线程单例模式
在单例模式的实现中,我们可以使用双重校验锁来提高程序效率:
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
此实现解决了前两个问题:安全和性能,因为只有第一次访问时才可能需要同步。但是在 JDK 1.5 之前的版本中,该运行效率并不是最优的。
枚举实现多线程单例模式
在 JDK 1.5 之后,我们可以使用枚举来实现多线程的单例模式:
public enum Singleton {
INSTANCE;
public void doSomething() {
// ...
}
}
通过枚举实现单例模式有以下优点:
- 线程安全
- 在任何情况下都是单例
- 序列化机制自动处理枚举单例
示例说明
示例一
假设我们有一个带参数的单例类:
public class SingletonWithParam {
private static SingletonWithParam instance;
private final int param;
private SingletonWithParam(int param) {
this.param = param;
}
public static synchronized SingletonWithParam getInstance(int param) {
if (instance == null) {
instance = new SingletonWithParam(param);
}
return instance;
}
}
但是在多线程环境中,可能容易出现多次重复创建对象的情况。
我们可以采用双重校验锁实现:
public class SingletonWithParam {
private static volatile SingletonWithParam instance;
private final int param;
private SingletonWithParam(int param) {
this.param = param;
}
public static synchronized SingletonWithParam getInstance(int param) {
if (instance == null) {
synchronized (SingletonWithParam.class) {
if (instance == null) {
instance = new SingletonWithParam(param);
}
}
}
return instance;
}
}
示例二
假设我们使用枚举实现一个无参的单例模式:
public enum Singleton {
INSTANCE;
public void doSomething() {
// ...
}
}
此时我们可以在任何地方使用该单例:
public class MyTask implements Runnable {
@Override
public void run() {
Singleton.INSTANCE.doSomething();
}
}
通过枚举实现的单例模式,在任何情况下都是线程安全的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程实战之单例模式与多线程的实例详解 - Python技术站