懒汉式单例模式会引来线程安全问题,即多线程时可能会创建多个实例,而且在反序列化时也可能会创建新的实例。看了大大们的实现方式,觉得以下一种比较简单方便理解。
一、下面是会造成线程安全的饿汉单例模式。用四打印下会发现hashcode不一致
public class Singleton {
private static Singleton instance = null;
//禁止new
private Singleton(){}
public static Singleton getInstance() {
if(instance == null){//懒汉式
instance = new MySingleton();
}
return instance;
}
}
二、静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性实现单例设计模式。
public class Singleton implements Serializable{
private static final long serialVersionUID = 1L;
private static Singleton instance = null;//饿汉式
//静态代码块实现单例模式线程安全
static {
instance = new Singleton();
}
public static Singleton getSingleton() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
//该方法在反序列化时会被调用
protected Object readResolve() throws ObjectStreamException {
System.out.println("调用了readResolve方法!");
return Singleton.instance;
}
}
三、多线程调用打印实例的hashCode
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Singleton.getSingleton().hashCode());
}
}
public static void main(String[] args) throws Exception {
MyThread[] mts = new MyThread[3];
for (int i = 0; i < mts.length; i++) {
mts[i] = new MyThread();
}
for (int j = 0; j < mts.length; j++) {
mts[j].start();
}
}
}
四、打印序列化和反序列后实例的hashcode
/**
* java类简单作用描述
*
* @Author: Sosmmh
* @CreateDate: 2018/2/27 10:56
**/
public class SaveAndReadForSingleton {
public static void main(String[] args) {
Singleton singleton = Singleton.getSingleton();
File file = new File("MySingleton.txt");
try {
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(singleton);
fos.close();
oos.close();
System.out.println(singleton.hashCode());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
Singleton rSingleton = (Singleton) ois.readObject();
fis.close();
ois.close();
System.out.println(rSingleton.hashCode());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
详细介绍请看原文大大。
详细介绍单例模式