更新時間:2022-03-23 11:42:35 來源:動力節點 瀏覽1688次
在本文中,我們將了解如何創建單例類。閱讀本文后,您將能夠根據您的使用、簡單性和消除瓶頸來創建您的單例類。
在 Java 中有很多方法可以做到這一點。所有這些方式在模式的實現上都有所不同,但最終,它們都實現了單個實例的相同最終結果。
這是創建單例類的最簡單方法。在這種情況下,類的對象是在JVM加載到內存時創建的。這是通過直接為引用分配一個實例來完成的。
當程序總是使用這個類的實例,或者創建實例的資源和時間成本不是太大時,可以使用它。
// Java code to create singleton class by
// Eager Initialization
public class GFG
{
// public instance initialized when loading the class
private static final GFG instance = new GFG();
private GFG()
{
// private constructor
}
public static GFG getInstance(){
return instance;
}
}
優點:
實現起來非常簡單。
可能導致資源浪費。因為類的實例總是被創建,無論它是否需要。
如果不需要,CPU 時間也會浪費在創建實例上。
異常處理是不可能的。
這也是 Eager 初始化的子部分。唯一的區別是對象是在靜態塊中創建的,因此我們可以訪問它的創建,例如異常處理。以這種方式,對象也是在類加載時創建的。
當使用急切初始化創建對象時有可能出現異常時,可以使用它。
// Java code to create singleton class
// Using Static block
public class GFG
{
// public instance
public static GFG instance;
private GFG()
{
// private constructor
}
static
{
// static block to initialize instance
instance = new GFG();
}
}
優點:
實現起來非常簡單。
無需實現 getInstance() 方法。可以直接訪問實例。
異常可以在靜態塊中處理。
可能導致資源浪費。因為類的實例總是被創建,無論它是否需要。
如果不需要,CPU 時間也會浪費在創建實例上。
在此方法中,僅在需要時才創建對象。這可以防止資源浪費。需要返回實例的 getInstance() 方法的實現。有一個空檢查,如果沒有創建對象然后創建,否則返回以前創建的。為了確保該類不能以任何其他方式實例化,構造函數是最終的。由于對象是在方法中創建的,因此它確保除非需要,否則不會創建對象。實例是私有的,因此沒有人可以直接訪問它。
它可以在單線程環境中使用,因為多個線程可以破壞單例屬性,因為它們可以同時訪問 get 實例方法并創建多個對象。
//Java Code to create singleton class
// With Lazy initialization
public class GFG
{
// private instance, so that it can be
// accessed by only by getInstance() method
private static GFG instance;
private GFG()
{
// private constructor
}
//method to return instance of class
public static GFG getInstance()
{
if (instance == null)
{
// if instance is null, initialize
instance = new GFG();
}
return instance;
}
}
優點:
只有在需要時才創建對象。它可以克服資源消耗和 CPU 時間的浪費。
在方法中也可以進行異常處理。
每次都必須檢查 null 的條件。
無法直接訪問實例。
在多線程環境中,它可能會破壞單例屬性。
創建了一個線程安全的單例,這樣即使在多線程環境中也可以保持單例屬性。為了使單例類線程安全,getInstance() 方法是同步的,因此多個線程不能同時訪問它。
// Java program to create Thread Safe
// Singleton class
public class GFG
{
// private instance, so that it can be
// accessed by only by getInstance() method
private static GFG instance;
private GFG()
{
// private constructor
}
//synchronized method to control simultaneous access
synchronized public static GFG getInstance()
{
if (instance == null)
{
// if instance is null, initialize
instance = new GFG();
}
return instance;
}
}
優點:
延遲初始化是可能的。
它也是線程安全的。
getInstance() 方法是同步的,因此會導致性能下降,因為多個線程無法同時訪問它。
在這種機制中,我們克服了同步代碼的開銷問題。在此方法中,getInstance 不同步,但創建實例的塊是同步的,因此必須等待最少數量的線程,這只是第一次。
// Java code to explain double check locking
public class GFG
{
// private instance, so that it can be
// accessed by only by getInstance() method
private static GFG instance;
private GFG()
{
// private constructor
}
public static GFG getInstance()
{
if (instance == null)
{
//synchronized block to remove overhead
synchronized (GFG.class)
{
if(instance==null)
{
// if instance is null, initialize
instance = new GFG();
}
}
}
return instance;
}
}
優點:
延遲初始化是可能的。
它也是線程安全的。
由于 synchronized 關鍵字,性能開銷得到了降低。
第一次,它會影響性能。
在Java5之前,內存模型有很多問題,以上方法在多線程環境中的某些場景下會導致失敗。所以,Bill Pugh 提出了一個內部靜態類的概念,用于單例。
// Java code for Bill Pugh Singleton Implementation
public class GFG
{
private GFG()
{
// private constructor
}
// Inner class to provide instance of class
private static class BillPughSingleton
{
private static final GFG INSTANCE = new GFG();
}
public static GFG getInstance()
{
return BillPughSingleton.INSTANCE;
}
}
加載單例類時,不會加載內部類,因此在加載類時不會創建對象。只有在調用 getInstance() 方法時才會創建內部類。所以它可能看起來像急切的初始化,但它是延遲初始化。
這是最廣泛Java單例設計模式使用的方法,因為它不使用同步。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習