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
*/