1、立即加载/“饿汉模式”:
没啥写的就不写了;太easy;
2、延迟加载/“懒汉模式”
延迟加载在多线程中根本不可能保持单例的状态,如示例:加载出了三个实例对象:
3、懒汉模式的解决方案1:声明synchronized关键字;
给getInstance方法加上synchronized关键字解决多线程下的懒汉模式问题
这种方法的缺点:运行效率非常低下,因为他是同步运行的;
4、懒汉模式的解决方案2:尝试同步代码块
尝试同步代码块:同样效率低下:
5、懒汉模式的解决方案3:针对某些关键的代码进行单独的同步:
懒汉模式的解决方案4:使用DCL双检查锁机制(Double Check Locking)来实现多线程环境中的延迟加载单例设计模式;
代码:
package Day01.Test;
/**
* @author Dangxuchao
* @Title: Test7
* @ProjectName 6.1 Java多线程编程核心技术第六章 :单例模式与多线程
* @Description: 延迟加载的解决方案4:
* 使用DCL双检查锁机制来实现多线程环境中的延迟加载单例设计模式;
* @date 2019/6/7 10:14
*/
class MyObject7 {
private static volatile MyObject7 myObject7;//volatile避免指令重排序
public MyObject7() {
}
public static MyObject7 getInstance(){
if (myObject7 == null){
synchronized (MyObject7.class){
if (myObject7 == null){
myObject7 = new MyObject7();
}
}
}
return myObject7;
}
}
class Thread7 extends Thread{
@Override
public void run() {
System.out.println(MyObject7.getInstance().hashCode());
}
}
public class Test7 {
public static void main(String[] args) {
Thread7 t1 = new Thread7();
Thread7 t2 = new Thread7();
Thread7 t3 = new Thread7();
t1.start();
t2.start();
t3.start();
}
}
/*
运行结果:
1211537232
1211537232
1211537232
*/
7、懒汉模式的解决方案5:使用静态内置类实现单例模式:
懒汉模式的解决方案5:序列化与反序列化实现;
内置类可以达到线程安全问题,但是如果遇到序列化对象时,使用默认的方式运行得到的结果还是多例的;
package Day01.Test;
import java.io.*;
/**
* @author Dangxuchao
* @Title: Test9
* @ProjectName 6.1 Java多线程编程核心技术第六章 :单例模式与多线程
* @Description: 8、懒汉模式的解决方案5:序列化与反序列化实现;
* @date 2019/6/7 10:49
*/
class MyObject9 implements Serializable{
private static final long serialVersionUID = 888L;
private static class MyObject9Handler{
private static final MyObject9 object9 = new MyObject9();
}
public MyObject9() {
}
public static MyObject9 getInstance(){
return MyObject9Handler.object9;
}
protected Object readResolve(){
System.out.println("调用了方法");
return MyObject9Handler.object9;
}
}
public class Test9 {
public static void main(String[] args) {
try{
MyObject9 myObject9 = MyObject9.getInstance();
FileOutputStream fosRef = new FileOutputStream(
new File("C:\\Users\\dangwuxie\\Desktop\\6-7.txt"));
ObjectOutputStream oosRef = new ObjectOutputStream(fosRef);
oosRef.writeObject(myObject9);
oosRef.close();
fosRef.close();
System.out.println(myObject9.hashCode());
}catch (FileNotFoundException a){
a.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
try {
FileInputStream fisRef = new FileInputStream(
new File("C:\\Users\\dangwuxie\\Desktop\\6-7.txt"));
ObjectInputStream iosRef = new ObjectInputStream(fisRef);
MyObject9 myObject9 = (MyObject9) iosRef.readObject();
iosRef.close();
fisRef.close();
System.out.println(myObject9.hashCode());
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
/*
运行结果:
1173230247
调用了方法
1173230247
*/