更新時(shí)間:2022-03-23 11:42:35 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1839次
在本文中,我們將了解如何創(chuàng)建單例類(lèi)。閱讀本文后,您將能夠根據(jù)您的使用、簡(jiǎn)單性和消除瓶頸來(lái)創(chuàng)建您的單例類(lèi)。
在 Java 中有很多方法可以做到這一點(diǎn)。所有這些方式在模式的實(shí)現(xiàn)上都有所不同,但最終,它們都實(shí)現(xiàn)了單個(gè)實(shí)例的相同最終結(jié)果。
這是創(chuàng)建單例類(lèi)的最簡(jiǎn)單方法。在這種情況下,類(lèi)的對(duì)象是在JVM加載到內(nèi)存時(shí)創(chuàng)建的。這是通過(guò)直接為引用分配一個(gè)實(shí)例來(lái)完成的。
當(dāng)程序總是使用這個(gè)類(lèi)的實(shí)例,或者創(chuàng)建實(shí)例的資源和時(shí)間成本不是太大時(shí),可以使用它。
// 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;
}
}
優(yōu)點(diǎn):
實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單。
可能導(dǎo)致資源浪費(fèi)。因?yàn)轭?lèi)的實(shí)例總是被創(chuàng)建,無(wú)論它是否需要。
如果不需要,CPU 時(shí)間也會(huì)浪費(fèi)在創(chuàng)建實(shí)例上。
異常處理是不可能的。
這也是 Eager 初始化的子部分。唯一的區(qū)別是對(duì)象是在靜態(tài)塊中創(chuàng)建的,因此我們可以訪問(wèn)它的創(chuàng)建,例如異常處理。以這種方式,對(duì)象也是在類(lèi)加載時(shí)創(chuàng)建的。
當(dāng)使用急切初始化創(chuàng)建對(duì)象時(shí)有可能出現(xiàn)異常時(shí),可以使用它。
// 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();
}
}
優(yōu)點(diǎn):
實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單。
無(wú)需實(shí)現(xiàn) getInstance() 方法。可以直接訪問(wèn)實(shí)例。
異常可以在靜態(tài)塊中處理。
可能導(dǎo)致資源浪費(fèi)。因?yàn)轭?lèi)的實(shí)例總是被創(chuàng)建,無(wú)論它是否需要。
如果不需要,CPU 時(shí)間也會(huì)浪費(fèi)在創(chuàng)建實(shí)例上。
在此方法中,僅在需要時(shí)才創(chuàng)建對(duì)象。這可以防止資源浪費(fèi)。需要返回實(shí)例的 getInstance() 方法的實(shí)現(xiàn)。有一個(gè)空檢查,如果沒(méi)有創(chuàng)建對(duì)象然后創(chuàng)建,否則返回以前創(chuàng)建的。為了確保該類(lèi)不能以任何其他方式實(shí)例化,構(gòu)造函數(shù)是最終的。由于對(duì)象是在方法中創(chuàng)建的,因此它確保除非需要,否則不會(huì)創(chuàng)建對(duì)象。實(shí)例是私有的,因此沒(méi)有人可以直接訪問(wèn)它。
它可以在單線程環(huán)境中使用,因?yàn)槎鄠€(gè)線程可以破壞單例屬性,因?yàn)樗鼈兛梢酝瑫r(shí)訪問(wèn) get 實(shí)例方法并創(chuàng)建多個(gè)對(duì)象。
//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;
}
}
優(yōu)點(diǎn):
只有在需要時(shí)才創(chuàng)建對(duì)象。它可以克服資源消耗和 CPU 時(shí)間的浪費(fèi)。
在方法中也可以進(jìn)行異常處理。
每次都必須檢查 null 的條件。
無(wú)法直接訪問(wèn)實(shí)例。
在多線程環(huán)境中,它可能會(huì)破壞單例屬性。
創(chuàng)建了一個(gè)線程安全的單例,這樣即使在多線程環(huán)境中也可以保持單例屬性。為了使單例類(lèi)線程安全,getInstance() 方法是同步的,因此多個(gè)線程不能同時(shí)訪問(wèn)它。
// 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;
}
}
優(yōu)點(diǎn):
延遲初始化是可能的。
它也是線程安全的。
getInstance() 方法是同步的,因此會(huì)導(dǎo)致性能下降,因?yàn)槎鄠€(gè)線程無(wú)法同時(shí)訪問(wèn)它。
在這種機(jī)制中,我們克服了同步代碼的開(kāi)銷(xiāo)問(wèn)題。在此方法中,getInstance 不同步,但創(chuàng)建實(shí)例的塊是同步的,因此必須等待最少數(shù)量的線程,這只是第一次。
// 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;
}
}
優(yōu)點(diǎn):
延遲初始化是可能的。
它也是線程安全的。
由于 synchronized 關(guān)鍵字,性能開(kāi)銷(xiāo)得到了降低。
第一次,它會(huì)影響性能。
在Java5之前,內(nèi)存模型有很多問(wèn)題,以上方法在多線程環(huán)境中的某些場(chǎng)景下會(huì)導(dǎo)致失敗。所以,Bill Pugh 提出了一個(gè)內(nèi)部靜態(tài)類(lèi)的概念,用于單例。
// 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;
}
}
加載單例類(lèi)時(shí),不會(huì)加載內(nèi)部類(lèi),因此在加載類(lèi)時(shí)不會(huì)創(chuàng)建對(duì)象。只有在調(diào)用 getInstance() 方法時(shí)才會(huì)創(chuàng)建內(nèi)部類(lèi)。所以它可能看起來(lái)像急切的初始化,但它是延遲初始化。
這是最廣泛Java單例設(shè)計(jì)模式使用的方法,因?yàn)樗皇褂猛健?/p>
相關(guān)閱讀
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)