1、
public class Singleton {
private Singleton()
{
System.out.println("創建單例");
}
private static Singleton instance = new Singleton();
public static Singleton getInstance()
{
return instance;
}
public static void otherStaticFunc()
{
System.out.println("其他方法");
}
public static void main(String[] args) {
Singleton.otherStaticFunc();
}
}
輸出:
創建單例
其他方法
不足分析:由於成員變量instance是static的,因此在JVM加載單例類時,就會被創建。此時就算調用該類中的其他方法,也會初始化instance,但是我們並沒有使用它。假如它的初始化要做的工作比較多,就會影響調用其他函數的速度。
因此引入延遲加載機制。
2、
public class LazySingleton {
public LazySingleton() {
System.out.println("延遲加載單例");
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance()
{
if(instance == null)
instance = new LazySingleton();
return instance;
}
public static void otherStaticFunc()
{
System.out.println("其他方法");
}
public static void main(String[] args) {
LazySingleton.otherStaticFunc();
}
}
輸出:
其他方法
將instance初始化爲空,確保類加載時無額外負擔,getInstance()必須用同步關鍵字synchronized修飾,否者在多線程環境下會出問題。第二種方法較第一種方法相比,雖然實現了延遲加載的功能,但引入了同步,它的耗時遠遠大於第一種單例模式。
因此還要繼續改進。
3、
public class StaticSingleton {
private StaticSingleton(){
System.out.println("內部內維護單例");
}
private static class SingletonHolder{
private static StaticSingleton instance = new StaticSingleton();
}
public static StaticSingleton getInstance(){
return SingletonHolder.instance;
}
public static void otherStaticFunc()
{
System.out.println("其他方法");
}
public static void main(String[] args) {
StaticSingleton.otherStaticFunc();
}
}
輸出:
其他方法
用內部類的方式來維護單例,因爲在類加載時,其內部類不會被初始化,genInstance()被調用時纔會加載SingletonHolder。由於實例的建立是在類加載時完成,故對多線程是友好 的,不需要使用同步關鍵字。