單例模式的基本介紹
雖然單例模式中的 HungerSingleton 可以保證只產生一個實體,但其中的資料還是需要做好同步化的動作。
首先標準的 Hunger Singleton

public class HungerSingleton
{
    private static final HungerSingleton sUniqueInstance = new HungerSingleton();
    private List<Integer> mNumbers = new ArrayList<Integer>();
    private HungerSingleton() {
        // Prevents singleton instance being instantiated from outside
    }
    public static HungerSingleton getInstance()
    {
        return sUniqueInstance;
    }
    public void addNumber(int number)
    {
        mNumbers.add(number);
    }
    public List<Integer> getNumbers()
    {
        return mNumbers;
    }
}

唯一不同的為第5行 mNumbers , 這個 List 將拿來做測試用,確保資料的同步化是否真的實現。
接著為Thread subclass

public class TestThread extends Thread
{
    @Override
    public void run()
    {
        for (int i = 0; i < 10; ++i) {
            HungerSingleton.getInstance().addNumber(i);
        }
    }
}

相當簡單,在 run 中會取得 HungerSingleton 的實體並把數值加到 mNumbers 中。
測試 Main class

public class Main
{
    public static void main(String[] args)
    {
        Thread thread = new TestThread();
        thread.start();
        Thread thread2 = new TestThread();
        thread2.start();
        try {
            Thread.currentThread().sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (Integer number : HungerSingleton.getInstance().getNumbers()) {
            System.out.println("number:" + number);
        }
    }
}

目標為讓 HungerSingleton 的 mNumbers 內容為 2 組 0 到 10 按照順序排列的數值。
執行結果

number:0
number:0
number:1
number:1
number:2
number:3
number:2
number:4
number:3
number:5
number:5
number:4
number:7
number:6
number:8
number:9
number:6
number:7
number:8
number:9

可以看到因為多執行緒的關係造成 mNumbers 內容排序錯亂。
加上同步化機制

public class TestThread extends Thread
{
    @Override
    public void run()
    {
        synchronized (HungerSingleton.getInstance()) {
            for (int i = 0; i < 100; ++i) {
                HungerSingleton.getInstance().addNumber(i);
            }
        }
    }
}

synchronized 可以讓一個執行緒取得指定物件的鎖,並擋住其他執行緒,直到該進入的執行緒完成函式內動作退出。
執行結果

number:0
number:1
number:2
number:3
number:4
number:5
number:6
number:7
number:8
number:9
number:0
number:1
number:2
number:3
number:4
number:5
number:6
number:7
number:8
number:9

從實驗結果可以看到雖然 HungerSingleton 可以保證只產生一個實體,但其內資料的操作還是需要加上同步化的動作。