日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

单例模式(饿汉式和懒汉式)

發布時間:2023/12/2 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单例模式(饿汉式和懒汉式) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??以前學習單例的時候,只理解了簡單部分。這次看DRP,對單例的餓漢式和懶漢式有了一些認識和對比。

? ?在實際的開發中,有些地方需要一個類只有一個實例。比如:網站在線人數的計數器,再比如IDE中的工具箱之類的等等。當需要這個類只有一個實例時,我們就需要使用到單例模式。單例模式有兩種實現方式:懶漢式(延遲加載)和 餓漢式(預加載)。

? ?目前遇到的情況使用餓漢式的比較多,也因為它比較簡單。代碼:

[java]?view plaincopy
  • public?class?ClientManager?{?????
  • ??????
  • ????private?static?ClientManager?instance?=?new?ClientManager();???//靜態私有成員,已初始化??
  • ??????
  • ????public?ClientManager(){?}??
  • ??????
  • ????public?static?ClientManager?getInstance(){?????//靜態,不用同步(類加載時已初始化,不會有多線程的問題)??
  • ????????return?instance;??
  • ????}??
  • }??
  • ? ?餓漢式:在類加載時就完成了初始化,所以類加載較慢,但獲取對象的速度快。這里getInstance()是static的,不用同步(類加載時已初始化,不會有多線程的問題)


    ? ?餓漢式程序運行過程中會節省時間,但是實例不管有沒有用到都會占用空間。在這方面懶漢式似乎比餓漢式優化。我們先看看代碼:

    [java]?view plaincopy
  • public?class?ClientManager??
  • ?{??
  • ????private?static?ClientManager?instance?=?null;??
  • ??????
  • ????private?ClientManager(){??
  • ??????????
  • ????}??
  • ??
  • ????public?static??ClientManager?getInstance(){?????//靜態,同步,公開訪問點??
  • ????????if(instance?==?null){??
  • ????????????return?new?ClientManager();??
  • ????????}??
  • ????????return?instance;??
  • ????}??
  • }??
  • ? ? 比較懶,在類加載時,不創建實例,因此類加載速度快,但運行時獲取對象的速度慢。這里getInstance()是static的。我們來想象一下:要使用ClientManager,直接調用類的getInstance()方法。第一次的時候發現instance是null,然后就新建一個對象,返回出去;第二次再使用的時候,因為這個instance是static的,所以已經不是null了,因此不會再創建對象,直接將其返回。那么為什么有同步的問題?

    ? ? 線程A希望使用ClientManager,調用getInstance()方法。因為是第一次調用,A就發現instance是null的,于是它開始創建實例,就在這個時候,CPU發生時間片切換,線程B開始執行,它要使用ClientManager,調用getInstance()方法,同樣檢測到instance是null——注意,這是在A檢測完之后切換的,也就是說A并沒有來得及創建對象——因此B開始創建。B創建完成后,切換到A繼續執行,因為它已經檢測完了,所以A不會再檢測一遍,它會直接創建對象。這樣,線程A和B各自擁有一個ClientManager的對象——單例失敗!

    ? ? 對于這種情況,我們很容易就想到加鎖來解決。那么加鎖后是怎么樣的?

    [java]?view plaincopy
  • public?class?ClientManager{???
  • ??
  • ??private?static?ClientManager?instance?=?null;???
  • ??????
  • ??public?synchronized?static?ClientManager?getInstance()?{?????//給方法加鎖??
  • ????if(instance?==?null)?{???
  • ??????instance?=?new?ClientManager();???
  • ????}???
  • ????return?instance;???
  • ??}???
  • ??????
  • ??private?ClientManager()?{???
  • ???????
  • ??}???
  • ??????
  • ??
  • }??
  • ? ?getInstance()加上同步鎖,一個線程必須等待另外一個線程創建完成后才能使用這個方法,這就保證了單例的唯一性。但是還有出現這樣一個性能問題:每次調用getInstants時都需要加鎖,會降低運行速度。所以我們還可以進一步改進。

    [java]?view plaincopy
  • public?class?ClientManager?{???
  • ??
  • ??private??static?ClientManager?instance?=?null;???
  • ??
  • ??public?static?ClientManager?getInstance()?{???
  • ????if?(instance?==?null)?{???
  • ??????synchronized?(ClientManager.class)?{???
  • ????????if(instance?==?null)?{???
  • ??????????instance?=?new?ClientManager();???
  • ????????}???
  • ??????}???
  • ????}???
  • ????return?instance;???
  • ??}???
  • ??
  • ??private?ClientManager()?{???
  • ??
  • ??
  • ??}???
  • ? ?這樣的方法可以雙重鎖定。我們一般用讓線程每次都加鎖,而只是實例未被創建的時候再加鎖處理,同時也能保證多線程的安全。為什么要進行兩次instance==null的判斷,這個交給大家自己想一下吧。就按照上面線程A和線程B這樣的方式。

    ? ?最后,總結一下餓漢式和懶漢式的區別:餓漢式類加載時已初始化,不會有多線程的問題,使用簡單。懶漢式是在需要時才對類進行實例化,但是有多線程問題,需要該考慮怎么加鎖的問題。

    總結

    以上是生活随笔為你收集整理的单例模式(饿汉式和懒汉式)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。