延遲加載(lazy load)是(也稱為懶加載),也叫延遲實例化,延遲初始化等,主要表達的思想就是:把對象的創建延遲到使用的時候創建,而不是對象實例化的時候創建。延遲加載機制是為了避免一些無謂的性能開銷而提出來的,這種方式避免了性能的浪費。所謂延遲加載就是當在真正需要數據的時候,才真正執行數據加載操作。可以簡單理解為,只有在使用的時候,才會發出sql語句進行查詢。
所謂延時加載技術,就是優化內存資源的利用效率,你要用什么,在用的時候再給你,而不是你遲點會用到的時候就馬上給你。
當創建一個對象的子對象開銷比較大時,而且有可能在程序中用不到這個子對象,那么就可以考慮用延遲加載的方式來創建子對象。另外就是當一個程序啟動時,需要創建多個對象,但僅有幾個對象需要立即使用,那么可以將一些不必要的初始化工作延遲到使用的時候。這樣可以提高程序的啟動速度。
實例一:
public Class Singleton
{
private static Singleton instance;
private Singleton(){ } //私有無參構造
public static Singleton getInstance(){
If(instance==null){
Instance=new Singleton();
}
Return instance;
}
}
構造函數私有,方法靜態。
問題:無法保證線程安全,當有多個線程同時訪問getInstance的時候,此時若對象為空,就會出現會多個線程同時產生多個Singleton對象。
此時我們可以修改一下上面的代碼,如實例二
實例二:
publicclass Singleton
{
privatestatic Singleton instance;
privatestaticobject _lock=newobject();
private Singleton()
{
}
publicstatic Singleton GetInstance()
{
if(instance==null)
{
lock(_lock)
{
if(instance==null)
{
instance=new Singleton();
}
}
}
return instance;
}
}
上述代碼使用了雙重鎖方式較好地解決了多線程下的單例模式實現。先看內層的if語句塊,使用這個語句塊時,先進行加鎖操作,保證只有一個線程可以訪問該語句塊,進而保證只創建了一個實例。再看外層的if語句塊,這使得每個線程欲獲取實例時不必每次都得加鎖,因為只有實例為空時(即需要創建一個實例),才需加鎖創建,若果已存在一個實例,就直接返回該實例,節省了性能開銷。
實例三:
public class Singleton
{
private static Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance()
{
return instance;
}
}
這個方法保證了在第一次加載的時候實例被初始化,且保證了線程安全。但是為進一步要求,我們想要在使用的時候才才初始化Singleton對象,及延遲加載。那么可以使用實例四方法。
實例四:
public class Singleton {
private Singleton() { };
private static class SingletonHolder {
static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
public static void main(String [] args){
Singleton.getInstance();
}
}
該方法中Singleton有一個靜態內部類SingletonHolder,內部類在外部加載的時候並不會加載,在有在調用getInstance才回加載。另外SingletonHolder類使用Private修飾以確保外部類不能訪問。