1.立即加載/餓漢模式
package singleton;
public class MyThread extends Thread{
?@Override
?public void run() {
??System.out.println(MyObject.getInstance().hashCode());
?}
}
package singleton;
public class MyObject {
?private static MyObject myObject = new MyObject();
?
?public static MyObject getInstance(){
??return myObject;
?}
}
package singleton;
public class Run {
?public static void main(String[] args) {
??MyThread t1 = new MyThread();
??MyThread t2 = new MyThread();
??MyThread t3 = new MyThread();
??t1.start();
??t2.start();
??t3.start();
?}
}
運(yùn)行結(jié)果皆為:
11077203
2.延遲加載/懶漢模式
package singleton;
public class MyObject2 {
?private static MyObject2?myObject;?public static MyObject2 getInstance() {
??try {
???if (myObject == null) {
????Thread.sleep(3000);//模擬在創(chuàng)建對(duì)象前做一些準(zhǔn)備工作
????myObject = new MyObject2();
???}
??} catch (InterruptedException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??return myObject;??????????????????
?}
}
在多線程中,就會(huì)出現(xiàn)取出多個(gè)實(shí)例的情況搔驼,與單例模式的初衷是相背離的迹栓。運(yùn)行結(jié)果為:
11077203
14576877
12677476
3.懶漢模式的改進(jìn)方法
3.1 整個(gè)getInstance()方法聲明synchronized關(guān)鍵字 替饿,但是效率太低。
3.2 在getInstance()方法里聲明MyObject.class的synchronized同步語(yǔ)句塊身堡,其實(shí)相當(dāng)于全部代碼被上鎖,效率依舊很低。
3.3 在某些重要的代碼實(shí)施同步語(yǔ)句塊楼眷,
package singleton;
public class MyObject3 {
?private static MyObject3?myObject;?public static MyObject3 getInstance() {
??try {
???if (myObject == null) {
????Thread.sleep(3000);
????synchronized(MyObject3.class){
?????myObject = new MyObject3();
????}
???}
??} catch (InterruptedException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??return myObject;??????????????????
?}
}
雖然大大提高效率,但是非線程安全熊尉,無(wú)效罐柳。
3.4 使用DCL雙檢查鎖機(jī)制 -- 推薦
package singleton;
public class MyObject4 {
?private volatile static MyObject4?myObject;?public static MyObject4 getInstance() {
??try {
???synchronized (MyObject4.class) {
????if (myObject == null) {
?????Thread.sleep(3000);
?????myObject = new MyObject4();
????}
???}
??} catch (InterruptedException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??return myObject;
?}
}
3.5 靜態(tài)內(nèi)部類方式
package singleton;
public class MyObject5 {
?private static class MyObjectHandler {
??private static MyObject5?myObject?= new MyObject5();
?}?public static MyObject5 getInstance() {
??return MyObjectHandler.myObject;
?}
}
3.6 序列化與反序列化解決:在反序列化中使用readResolve()方法(略)。
3.7 使用static代碼塊實(shí)現(xiàn):
package singleton;
public class MyObject6 {
?private static MyObject6?instance?= null;?static {
??instance = new MyObject6();
?}?public static MyObject6 getInstance() {
??return instance;
?}
}
3.8 使用枚舉數(shù)據(jù)類型enum:
使用枚舉類時(shí)狰住,構(gòu)造方法會(huì)被自動(dòng)調(diào)用张吉。(但不要將枚舉類進(jìn)行曝露,應(yīng)將枚舉類包裝在一個(gè)正常類中催植,遵守職責(zé)單一原則)