Chapter 6
第六章主要介紹如何使單例模式遇到多線程是安全的、正确的
- 立即加載/”餓漢式”
/**
* 立即加載單例模式/”餓漢式“
* Created by boboan on 2018/6/5.
*/
public class MyObject {
private static MyObject myObject = new MyObject();
public MyObject() {
}
public static MyObject getInstance(){
return myObject;
}
}
- 延遲加載/”懶漢式”
/**
* 延遲加載單例模式/"懶漢式"
*
* Created by boboan on 2018/6/5.
*/
public class MyObject2 {
private static MyObject2 myObject;
public MyObject2() {
}
public static MyObject2 getInstance(){
if (myObject != null) {
}else {
return myObject = new MyObject2();
}
return myObject;
}
}
但是這種方法在多線程的情況是錯誤的,出現多例的情況
/**
* 延遲加載單例模式/"懶漢式"
*
* Created by boboan on 2018/6/5.
*/
public class MyObject3 {
private static MyObject3 myObject;
public MyObject3() {
}
//設定同步方法效率比較低
//給方法加鎖
synchronized public static MyObject3 getInstance(){
try {
if (myObject != null) {
}else {
Thread.sleep();
return myObject = new MyObject3();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
這種方法在多線程是錯誤的,可以通過加 synchronized 同步來解決
/**
* 延遲加載單例模式/"懶漢式"
*
* Created by boboan on 2018/6/5.
*/
public class MyObject4 {
private static MyObject4 myObject;
public MyObject4() {
}
public static MyObject4 getInstance(){
try {
if (myObject != null) {
}else {
synchronized (MyObject4.class) {
Thread.sleep();
return myObject = new MyObject4();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
synchronized 同步效率低,采用同步代碼塊,對關鍵代碼同步效率稍微提升,但是多線程下還是無法解決
- DCL 雙檢查鎖機制(推薦)
/**
* 延遲加載單例模式/"懶漢式"
*
* Created by boboan on 2018/6/5.
*/
public class MyObject5 {
private volatile static MyObject5 myObject;
public MyObject5() {
}
public static MyObject5 getInstance(){
try {
if (myObject != null) {
}else {
Thread.sleep();
synchronized (MyObject5.class) {
if (myObject==null) {
myObject = new MyObject5();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return myObject;
}
}
DCL 雙檢查鎖機制來解決問題,保證了不需要同步代碼塊的異步執行,又保證了單例的效果
- 靜态内置類實作單例模式(推薦)
/**
* 靜态内置類實作單例模式
*
* Created by boboan on 2018/6/5.
*/
public class MyObject6 {
private static class MyObjectHandler{
private static MyObject myObject = new MyObject();
}
public MyObject6() {
}
public static MyObject getInstance(){
return MyObjectHandler.myObject;
}
}
- 序列化與反序列化實作單例模式
**
* 序列化與反序列化實作單例模式
* 避免枚舉類暴露
*
* Created by boboan on //
*/
public class MyObject10 implements Serializable{
public static final long seriVersionUID = L;
public static class MyObjectHandler{
private static final MyObject10 myObject10= null;
}
private MyObject10(){
}
public static MyObject10 getInstance(){
return MyObjectHandler.myObject10;
}
protected Object readResolve(){
System.out.println("調用了 read 方法");
return MyObjectHandler.myObject10;
}
}
- static 代碼塊實作單例模式
/**
* static 代碼塊實作單例模式
*
* Created by boboan on 2018/6/5.
*/
public class MyObject7 {
private static MyObject myObject = null;
public MyObject7() {
}
static {
myObject = new MyObject();
}
public static MyObject getInstance(){
return myObject;
}
}
靜态代碼塊在使用類的時候就執行了,利用此特性實作單例
- enum 枚舉資料類型實作單例模式
/**
* 枚舉類實作單例模式
* 避免枚舉類暴露
*
* Created by boboan on 2018/6/5.
*/
public class MyObject9 {
public enum MyenumSingleton{
connectionFactory;
private int tag;
private MyenumSingleton() {
System.out.println("調用了");
tag = ;
}
public int getTag(){
return tag;
}
}
public static int getComTag(){
return MyenumSingleton.connectionFactory.getTag();
}
}
使用枚舉類時,構造方法會被自動調用。是以可以用來建立單例