文章目录
本文讲解:单例模式在多线程技术上的实现方式
1.1 天生线程安全的饿汉式单例
//饿汉式单例类(线程安全):在类初始化时,已经自行实例化
public class MySingleton {
private static MySingleton instance = new MySingleton();
private MySingleton(){}
public static MySingleton getInstance() {
return instance;
}
}
1.2 懒汉式单例
- 懒汉式单例:在方法调用获取实例时才创建实例。
1.2.1 线程不安全的懒汉式单例
public class MySingleton {
private static MySingleton instance = null;
private MySingleton(){}
public static MySingleton getInstance() {
if(instance == null){
instance = new MySingleton();
}
return instance;
}
}
1.2.2 线程安全的懒汉式单例
1. 同步方法实现
public class MySingleton {
private static MySingleton instance = null;
private MySingleton(){}
public static synchronized MySingleton getInstance() { // 加synchronized
if(instance == null){
instance = new MySingleton();
}
return instance;
}
}
2. 同步代码块实现:双重检查锁定(Double Check Locking ,DCL)—推荐
public class MySingleton {
private static MySingleton instance = null;
private MySingleton(){}
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
1.3 使用静态内部类实现单例模式
- 保证多线程并发下的线程安全性。
public class MySingleton {
private MySingleton(){}
//内部类:只在第一次使用时加载
private static class MySingletonHandler{
private static MySingleton instance = new MySingleton();
}
public static MySingleton getInstance() {
return MySingletonHandler.instance;
}
}
1.4 序列化与反序列化的单例模式实现
- 上述1.3中静态内部类的实现方式虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的,代码如下。
public class MySingleton implements Serializable { private static final long serialVersionUID = 1L; private MySingleton(){} //内部类 private static class MySingletonHandler{ private static MySingleton instance = new MySingleton(); } public static MySingleton getInstance() { return MySingletonHandler.instance; //序列化时,会得到多例 } } // 测试 public class Test{ public static void main(String[] args) throws { MySingleton singleton = MySingleton.getInstance(); File file = new File("MySingleton.txt"); // 序列化 FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(singleton); fos.close(); oos.close(); // 反序列化 FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis); MySingleton rSingleton = (MySingleton) ois.readObject(); fis.close(); ois.close(); } }
- 解决:在反序列化的过程中使用readResolve()方法
public class MySingleton implements Serializable { private static final long serialVersionUID = 1L; private MySingleton(){} //内部类 private static class MySingletonHandler{ private static MySingleton instance = new MySingleton(); } public static MySingleton getInstance() { return MySingletonHandler.instance; } protected Object readResolve() throws ObjectStreamException { return MySingletonHandler.instance; } }
1.5 使用static代码块实现单例
public class MySingleton{
private static MySingleton instance = null;
//静态代码块
static{
instance = new MySingleton();
}
private MySingleton(){}
public static MySingleton getInstance() {
return instance;
}
}
1.6 使用enum枚举数据类型实现单例模式
- 枚举类的构造方法在类加载是被实例化
public class ClassFactory{
private enum MyEnumSingleton{
singletonFactory;
private MySingleton instance;
private MyEnumSingleton(){ //枚举类的构造方法在类加载是被实例化
instance = new MySingleton();
}
public MySingleton getInstance(){
return instance;
}
}
public static MySingleton getInstance(){
return MyEnumSingleton.singletonFactory.getInstance();
}
}
class MySingleton{//需要获实现单例的类,比如数据库连接Connection
public MySingleton(){}
}