1. 程式人生 > >Java多執行緒--單例模式的五種實現

Java多執行緒--單例模式的五種實現

一、惡漢模式

在這個類還沒有使用到的時候就已經建立好了

public class Singleton{
    /**
     *類變數在類準備階段就初始化了然後放在<clinit>構造方法中,
     *一旦外部呼叫了靜態方法,那麼就會初始化完成。
    */
    private static Singleton instance = new Singleton();
    private Singleton(){
    }
    public static Singleton getInstance(){
        return instance;
    }
}

二、懶漢模式-非執行緒安全

在需要獲取Singleton物件的時候才去建立這個物件

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){
    }
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

三、懶漢模式-執行緒安全

當兩個執行緒同時執行到判斷這個Singleton的例項instance是否為空的時候,兩個執行緒都判斷為空,那麼這個時候就會返回兩個例項,這樣一來就不是單例模式了。因此我們想到在方法上進行加鎖。

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){
    }
    public synchronized static  Singleton getInstance(){
        if(instance == null
){ instance = new Singleton(); } return instance; } }

這個方式的使得一個執行緒等待的時候過程,降低併發效能。因此想到使用下面的方法

四、懶漢模式-雙檢鎖

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){
    }
    public static  Singleton getInstance(){
        if(instance == null){
            synchronized(Singleton.class){
                if(instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

我們使用synchronized這個關鍵字將鎖住一個程式碼塊,一旦一個執行緒獲得了這個物件鎖,那麼另一個執行緒就只能等待。當一個執行緒構造例項完成以後,另一個執行緒就進入判斷條件會發現我們的例項初始化過了,不再為null。此時返回例項物件。

五、靜態內部類

惡漢模式利用虛擬機器載入類的特性初始化例項物件,而懶漢模式則是在類被使用的時候才會被初始化。靜態內部類,當我們的類在載入的時候不會執行,只是在類被外界使用的時候才會被初始化。因此這種方式既實現了延遲載入又實現了執行緒安全。(這裡會不會出現安全洩漏問題)


public class Singleton{
    private static Singleton instance = null;
    static{
        instance = new Singleton();
    }
    private Singleton(){
    }
    public static  Singleton getInstance(){
        return Singleton.instance;
    }
}

測試程式碼

package JingDongProgram;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class Test8 {
    public static void main(String[] args){

        Callable<Singleton> t1 = new Thread8();
        FutureTask<Singleton> f1 = new FutureTask<Singleton>(t1);
        Callable<Singleton> t2 = new Thread9();
        FutureTask<Singleton> f2 = new FutureTask<Singleton>(t1);
        new Thread(f1).start();
        new Thread(f2).start();

    }
}
class Thread8 implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println(Singleton.getInstance());
        return null;
    }
}
class Thread9 implements Callable{
    @Override
    public Object call() throws Exception {
        System.out.println(Singleton.getInstance());
        return null;
    }
}

輸出結果

JingDongProgram.Singleton@2410eb3b
JingDongProgram.Singleton@2410eb3b

六、列舉類

public enum Singleton{
    INSTANCE;
}

七、參考文章