java線程單例
Ⅰ java 單例模式這個要怎麼理解
單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
注意:
1、單例類只能有一個實例。
2、單例類必須自己創建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。
介紹
意圖:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
主要解決:一個全局使用的類頻繁地創建與銷毀。
何時使用:當您想控制實例數目,節省系統資源的時候。
如何解決:判斷系統是否已經有這個單例,如果有則返回,如果沒有則創建。
關鍵代碼:構造函數是私有的。
應用實例:
1、一個班級只有一個班主任。
2、Windows 是多進程多線程的,在操作一個文件的時候,就不可避免地出現多個進程或線程同時操作一個文件的現象,所以所有文件的處理必須通過唯一的實例來進行。
3、一些設備管理器常常設計為單例模式,比如一個電腦有兩台列印機,在輸出的時候就要處理不能兩台列印機列印同一個文件。
優點:
1、在內存里只有一個實例,減少了內存的開銷,尤其是頻繁的創建和銷毀實例(比如管理學院首頁頁面緩存)。
2、避免對資源的多重佔用(比如寫文件操作)。
缺點:沒有介面,不能繼承,與單一職責原則沖突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。
使用場景:
1、要求生產唯一序列號。
2、WEB 中的計數器,不用每次刷新都在資料庫里加一次,用單例先緩存起來。
3、創建的一個對象需要消耗的資源過多,比如 I/O 與資料庫的連接等。
注意事項:getInstance() 方法中需要使用同步鎖 synchronized (Singleton.class) 防止多線程同時進入造成 instance 被多次實例化。
Ⅱ Java模式設計之單例模式(一)
作為對象的創建模式[GOF ] 單例模式確保某一個類只有一個實例 而且自行實例化並向整個系統提供這個實例 這個類稱為單例類
單例模式的要點
單例單例
顯然單例模式的要點有三個 一是某各類只能有一個實例 二是它必須自行創建這個事例 三是它必須自行向整個系統提供這個實例 在下面的對象圖中 有一個 單例對象 而 客戶甲 客戶乙 和 客戶丙 是單例對象的三個客戶對象 可以看到 所有的客戶對象共享一個單例對象 而且從單例對象到自身的連接線可以看出 單例對象持有對自己的引用
資源管理
一些資源管理器常常設計成單例模式
在計算機系統中 需要管理的資源包括軟體外部資源 譬如每台計算機可以有若干個列印機 但只能有一個Printer Spooler 以避免兩個列印作業同時輸出到列印機中 每台計算機可以有若干傳真卡 但是只應該有一個軟體負責管理傳真卡 以避免出現兩份傳真作業同時傳到傳真卡中的情況 每台計算機可以有若干通信埠 系統應當集中管理這些通信埠 以避免一個通信埠同時被兩個請求同時調用
需要管理的資源包括軟體內部資源 譬如 大多數的軟體都有一個(甚至多個)屬性(properties)文件存放系統配置 這樣的系統應當由一個對象來管理一個屬性文件
需要管理的軟體內部資源也包括譬如負責記錄網站來訪人數的部件 記錄軟體系統內部事件 出錯信息的部件 或是對系統的表念螞現進行檢查的部件等 這些部件都必須集中管理 不可政出多頭
這些資源管理器構件必須只有一個實例 這是其一 它們必須自行初始化 這是其二 允許整個系統訪問自己這是其三 因此 它們都滿足單例模式的條件 是單例模式的應用
一個例子 Windows 回收站
Windows x 以後的視窗系統中都有一個回收站 下圖就顯示了Windows 的回收站
在整個視窗系塵高核統中 回收站只能有一個實例 整個系統都使用這個惟一的實例 而且回收站自行提供自己的實例 因此 回收站是單例模式的應用
雙重檢查成例
在本章最後的附錄里研究了雙重檢查成例 雙重檢查成例與單例模式並無直接的關系 但是由於很多C 語言設計師在單例模式裡面使用雙重檢查成例 所以這一做法也被很多Java 設計師所模仿 因此 本書在附錄里提醒讀者 雙重檢查成例在Java 語言里並不能成立 詳情請見本章的附錄
單例模式的結構
單例模式有以下的特點
…… 單例類只可有一個實例
…… 單例類必須自己創建自己這惟一的實例
…… 單例類必須給所有其他對象提供這一實例
雖然單例模式中的單例類被限定只能有一個實例 但是單例模式和單例類可以很容易被推廣到任意且有限多個實例的情況 這時候稱它為多例模式(Multiton Pattern) 和多例類(Multiton Class) 請見 專題 多例(Multiton )模式與多語言支持 一章 單例類的簡略類圖如下所示
由於Java 語言的特點 使得單例模式在Java 語言的實現上有自己的特點 這些特點主要表現在單例類如何將自己實例化上
餓漢式單例類餓漢式單例類是在Java 語言里實現得最為簡便的單例類 下面所示的類圖描述了一個餓漢式單例類的典型實現
從圖中可以看出 此類已經自已將自己實例化
代碼清單 餓漢式單例類
public class EagerSingleton { private static final EagerSingleton m_instance = new EagerSingleton() /** * 私有的默認構造子*/ private EagerSingleton() { } /** * 靜態工廠方法*/ public static EagerSingleton getInstance()
{
Java 與模式return m_instance }
讀者可以看出 在這個類被載入時 靜態變數m_instance 會被初始化 此時類的私有構造子會被調用 這時候 單例類的惟一實例就被創建出來了
Java 語言中單例類的一個最重要的特點是類派掘的構造子是私有的 從而避免外界利用構造子直接創建出任意多的實例 值得指出的是 由於構造子是私有的 因此 此類不能被繼承
懶漢式單例類
與餓漢式單例類相同之處是 類的構造子是私有的 與餓漢式單例類不同的是 懶漢式單例類在第一次被引用時將自己實例化 如果載入器是靜態的 那麼在懶漢式單例類被載入時不會將自己實例化 如下圖所示 類圖中給出了一個典型的餓漢式單例類實現
代碼清單 懶漢式單例類
package javapatterns singleton demos public class LazySingleton { private static LazySingleton m_instance = null /** * 私有的默認構造子 保證外界無法直接實例化*/ private LazySingleton() { } /** * 靜態工廠方法 返還此類的惟一實例*/ synchronized public static LazySingleton getInstance()
{ if (m_instance == null)
{ m_instance = new LazySingleton() } return m_instance }
讀者可能會注意到 在上面給出懶漢式單例類實現里對靜態工廠方法使用了同步化 以處理多線程環境 有些設計師在這里建議使用所謂的 雙重檢查成例 必須指出的是 雙重檢查成例 不可以在Java 語言中使用 不十分熟悉的讀者 可以看看後面給出的小節
同樣 由於構造子是私有的 因此 此類不能被繼承 餓漢式單例類在自己被載入時就將自己實例化 即便載入器是靜態的 在餓漢式單例類被載入時仍會將自己實例化 單從資源利用效率角度來講 這個比懶漢式單例類稍差些
從速度和反應時間角度來講 則比懶漢式單例類稍好些 然而 懶漢式單例類在實例化時 必須處理好在多個線程同時首次引用此類時的訪問限制問題 特別是當單例類作為資源控制器 在實例化時必然涉及資源初始化 而資源初始化很有可能耗費時間 這意味著出現多線程同時首次引用此類的機率變得較大
餓漢式單例類可以在Java 語言內實現 但不易在C++ 內實現 因為靜態初始化在C++ 里沒有固定的順序 因而靜態的m_instance 變數的初始化與類的載入順序沒有保證 可能會出問題 這就是為什麼GoF 在提出單例類的概念時 舉的例子是懶漢式的 他們的書影響之大 以致Java 語言中單例類的例子也大多是懶漢式的 實際上 本書認為餓漢式單例類更符合Java 語言本身的特點
登記式單例類
登記式單例類是GoF 為了克服餓漢式單例類及懶漢式單例類均不可繼承的缺點而設計的 本書把他們的例子翻譯為Java 語言 並將它自己實例化的方式從懶漢式改為餓漢式 只是它的子類實例化的方式只能是懶漢式的 這是無法改變的 如下圖所示是登記式單例類的一個例子 圖中的關系線表明 此類已將自己實例化
代碼清單 登記式單例類
import java util HashMap public class RegSingleton { static private HashMap m_registry = new HashMap() static { RegSingleton x = new RegSingleton() m_registry put( x getClass() getName() x) } /** * 保護的默認構造子*/ protected RegSingleton() {} /** * 靜態工廠方法 返還此類惟一的實例*/ static public RegSingleton getInstance(String name)
{ if (name == null)
{ name = javapatterns singleton demos RegSingleton } if (m_registry get(name) == null)
{ try { m_registry put( name Class forName(name) newInstance() ) } catch(Exception e)
{ System out println( Error happened ) } return (RegSingleton) (m_registry get(name) ) } /** * 一個示意性的商業方法*/ public String about()
{ return Hello I am RegSingleton }它的子類RegSingletonChild 需要父類的幫助才能實例化 下圖所示是登記式單例類子類的一個例子 圖中的關系表明 此類是由父類將子類實例化的
下面是子類的源代碼
代碼清單 登記式單例類的子類
import java util HashMap public class RegSingletonChild extends RegSingleton { public RegSingletonChild() {} /** * 靜態工廠方法*/ static public RegSingletonChild getInstance()
{ return (RegSingletonChild)
RegSingleton getInstance( javapatterns singleton demos RegSingletonChild ) } /** * 一個示意性的商業方法*/ public String about()
{ return Hello I am RegSingletonChild }
在GoF 原始的例子中 並沒有getInstance() 方法 這樣得到子類必須調用的getInstance(String name)方法並傳入子類的名字 因此很不方便 本章在登記式單例類子類的例子里 加入了getInstance() 方法 這樣做的好處是RegSingletonChild 可以通過這個方法 返還自已的實例 而這樣做的缺點是 由於數據類型不同 無法在RegSingleton 提供這樣一個方法 由於子類必須允許父類以構造子調用產生實例 因此 它的構造子必須是公開的 這樣一來 就等於允許了以這樣方式產生實例而不在父類的登記中 這是登記式單例類的一個缺點
lishixin/Article/program/Java/gj/201311/27416
Ⅲ java 單例模式
System.out.println (Singleton.getInstance());
System.out.println (Singleton.getInstance());
main 函數中有這兩句,一摸一樣。
第一句執行的時候,第一次調用getInstance(),意思是要獲取Singleton的一個對象實例。
而正常情況下,我們要獲取對象的話是用 new Singleton(),這個方法的,但是這個方法在Singleton裡面被聲明為:private ,意思是外界不能調用。
不能調用,我怎麼用你的對象?
Singleton裡面實現了生成對象的方法,getInstance(),你要用他的對象就必須調用這個方法。
而這個方法裡面你也看到了,如果
if(instance == null){
instance = new Singleton();
}
如果沒有實例則創建一個新的,但是已經創建過的話,就返回已經存在的實例。
所以輸出結果:
net.chelson.chapter5.Singleton@de6ced
net.chelson.chapter5.Singleton@de6ced
你兩次調用的這個對象的內存地址都是相同的,也就是說,是同一個東西(對象)
這個總的來說就是:
類的構造方法私有化(防止外界構造新對象)
提供獲取實例的方法(用於外界調用)
作用:用於提供只能有一個實例的對象。
Ⅳ 關於JAVA單例的問題
這個問題由最開始使用JACKSON JSON而衍生出來 因為官網上建議將ObjectMapper作為全局變數使用從而提高效率 所以 我們項目裡面使用了單例 在使用單例的時候 我們無可厚非的考慮了資源在使用時是否要保證互斥的情況
最開始的寫法
Java代碼
public final class JacksonJsonMapper {
static volatile ObjectMapper objectMapper = null;
private JacksonJsonMapper(){}
public static ObjectMapper getInstance(){
if (objectMapper==null){
objectMapper = new ObjectMapper();
}
return objectMapper;
}
}
在此期間 我考慮了兩個問題 並與團隊中的另外一個兄弟發生了激烈的討論
在使用getInstance()方法的時候 是否要使用synchronized關鍵字
在使用objectMapper writeValueAsString(object)時 因為此方法非靜態方法 在此方法內是否會使用到對象自有的屬性 而在並發的時候出現前者屬性被後者銀並搏覆蓋的問題
後再看了源碼後 排除了第鋒祥二個顧慮 ObjectMapper是與線程綁定的 所以是線程安全的 並且也在官網的線程安全介紹中得到了證實
Jackson follows thread safety rules typical for modern factory based Java data format handlers (similar to what say Stax or JAXP implementations do) For example:
Factories (ObjectMapper JsonFactory) are thread safe once configured: so ensure that all configuration is done from a single thread and before instantiating anything with factory
Reader/writer instances (like JsonParser and JsonParser) are not thread safe there is usually no need for them to be but if for some reason you need to access them from multiple threads external synchronization is needed
All transformer objects (custom serializers deserializers) are expected to be stateless and thereby thread safe state has to be stored somewhere outside instances (in ThreadLocal or context objects passed in like DeserializationContext)
第一個顧慮在看完下面這篇文章蔽漏後 得到了解決方法
l
Java代碼
public final class JacksonJsonMapper {
static volatile ObjectMapper objectMapper = null;
private JacksonJsonMapper(){}
public static ObjectMapper getInstance(){
if (objectMapper==null){
synchronized (ObjectMapper class) {
if (objectMapper==null){
objectMapper = new ObjectMapper();
}
}
}
return objectMapper;
}
}
lishixin/Article/program/Java/gj/201311/27515
Ⅳ 什麼是Java單例模式啊
樓主您好
java模式之單例模式:
單例模式確保一個類只有一個實例,自行提供這個實例並向整個系統提供這個實例。
特點:
1,一個類只能有一個實例
2,自己創建這個實例
3,整個系統都要使用這個實例
例: 在下面的對象圖中,有一個"單例對象",而"客戶甲"、"客戶乙" 和"客戶丙"是單例對象的三個客戶對象。可以看到,所有的客戶對象共享一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。
Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。在很多操作中,比如建立目錄 資料庫連接都需要這樣的單線程操作。一些資源管理器常常設計成單例模式。
外部資源:譬如每台計算機可以有若干個列印機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到列印機中。每台計算機可以有若干個通信埠,系統應當集中管理這些通信埠,以避免一個通信埠被兩個請求同時調用。內部資源,譬如,大多數的軟體都有一個(甚至多個)屬性文件存放系統配置。這樣的系統應當由一個對象來管理這些屬性文件。
一個例子:Windows 回收站。
在整個視窗系統中,回收站只能有一個實例,整個系統都使用這個惟一的實例,而且回收站自行提供自己的實例。因此,回收站是單例模式的應用。
兩種形式:
1,餓漢式單例類
public class Singleton {
private Singleton(){}
//在自己內部定義自己一個實例,是不是很奇怪?
//注意這是private 只供內部調用
private static Singleton instance = new Singleton();
//這里提供了一個供外部訪問本class的靜態方法,可以直接訪問
public static Singleton getInstance() {
return instance;
}
}
2,懶漢式單例類
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個方法比上面有所改進,不用每次都進行生成對象,只是第一次
//使用時生成實例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
第二中形式是lazy initialization,也就是說第一次調用時初始Singleton,以後就不用再生成了。