單例(SingLeton
)故名思義就是在一個JVM運行中只有一個對象存在;請你務必注意到是在一個JVM虛擬機內。
今天一個朋友問過這樣一個問題:為什么他的單例每次都進入構造函數,程序如下:
public?class?ServerThread?implements?Runnable{
?????private?static?ServerThread?instance?=?null;??
?????private?ServerThread()?{
?????????try?{
?????????????if?(socket?==?null)?{
?????????????????socket?=?new?DatagramSocket(Constants.SERVER_PORT);
?????????????}
??????????}?catch?(Exception?e)?{
?????????????????e.printStackTrace();
???????????}
???????}
?????public?static?final?ServerThread?getInstance()?{
????????if?(instance?==?null)?{
???????????System.out.println("instance?is?null
?new?generate
.");
???????????instance?=?new?ServerThread();
????????}
????????return?instance;
??????}
????public?Thread?getThreadInstance()?{
????????if?(threadInstance?==?null)?{
????????????threadInstance?=?new?Thread(instance);
????????}
????????return?threadInstance;
????}
。。。。。。。。
}
public?class?Main?{
??????main函數有servTr?=?ServerThread.getInstance().getThreadInstance();一句
代碼沒有問題吧;為什么他的單例每次都進入構造函數呢?
細問之下才知道了他啟動了兩次Main類;啟動一個Main類便在一個JVM,兩次的單例怎么能是同一個呢?!
記住:是在同一個JVM中唯一,不是在一個物理內存中唯一。當然后者不是不能做到的,分布式對象嘛,呵呵。
第二點就是:單例的構造:
目前方式多種,我認為只有兩種是正確的:
第一:private final static DaoFactory instance = new DaoFactory();
第二:
private?static?DaoFactory?instance?=?null;
??????private?Properties?props?=?null;
???????private?Map?daos?=?null;
??????private?DaoFactory()?{
???????????props?=?new?Properties();
???????????daos?=?new?HashMap();
??????}
?????
??????public?static?DaoFactory?getInstance()?{
???????????while?(null?==?instance)?{
?????????????????synchronized(DaoFactory.class)?{
??????????????????????if?(null?==?instance)?{
????????????????????????????instance?=?new?DaoFactory();
????????????????????????????instance.initDaoFactroy();
??????????????????????}
?????????????????}
???????????}
???????????return?instance;
??????}
看清楚了,這里用的是while;不是if。
為什么不能用if呢?下面的一個例子說明
public?class?DomainFactory?{
??????private?List?provinces;
?
???????????private?Map?domains;
??????private?static?DomainFactory?instance;
??????private?DomainFactory()?{
???????????generateDomainTree();
??????}
??????public?static?DomainFactory?getInstance()?{
???????????if?(null?==?instance)?{
?????????????????synchronized?(DomainFactory.class)?{
??????????????????????if?(null?==?instance)?{
????????????????????????????instance?=?new?DomainFactory();
??????????????????????}
?????????????????}
???????????}
???????????return?instance;
??????}
??????private?void?generateDomainTree()?{
。。。。。
}
?public?class?CategoryFactory?{
??????private?Map?map;?????
??????private?static?CategoryFactory?instance;
?????
??????private?CategoryFactory()?{
???????????map?=?new?HashMap();
???????????generateCategoryTree();
??????}?????
??????public?static?CategoryFactory?getInstance()?{
???????????if?(null?==?instance)?{
?????????????????synchronized?(CategoryFactory.class)?{
??????????????????????if?(null?==?instance)?{
????????????????????????????instance?=?new?CategoryFactory();
??????????????????????}
?????????????????}
???????????}
???????????return?instance;
??????}?????
??????private?void?generateCategoryTree()?{
。。。。。。
}
?
public?class?SearchAction?extends?DispatchAction?{
??????public?ActionForward?getCatalogData(ActionMapping?mapping,?ActionForm?form,
?????????????????HttpServletRequest?request,?HttpServletResponse?response)?{
???????????DomainObject?domainObject?=?new?DomainObject();
???????????domainObject.setCity("b");
???????????request.getSession().setAttribute("domainObject",?domainObject);
???????????request.setAttribute("domains",?DomainFactory.getInstance().getCity(domainObject.getCity()));
???????????return?mapping.findForward("left");
??????}????
?
??????public?ActionForward?getCatalogDataCategory(ActionMapping?mapping,?ActionForm?form,
?????????????????HttpServletRequest?request,?HttpServletResponse?response)?{
???????????request.setAttribute("productCategories",?CategoryFactory.getInstance().getRootProductCategories());
???????????return?mapping.findForward("body");
??????}
<frameset?rows="80,668*"?cols="*"?frameborder="no"?border="0"?framespacing="0">
????<frame?name="header"?src="./search_header.jsp"?scrolling="no"?title="header"?noresize="noresize">
????<frameset?cols="180,*"?frameborder="yes"?border="0"?framespacing="0">
???????<frame?name="left"?scrolling="no"?src="search.html?method=getCatalogData"?target="_self"?noresize="noresize">
???????<frame?name="body"?scrolling="yes"?src="search.html?method=getCatalogDataCategory"?scrolling="yes"?target="_self"?noresize="noresize">
??</frameset>
</frameset>
用if 出錯了吧?為什么,同時進入了if(null == instance)的判斷,然后爭奪鎖;結果爭奪不到的只能在爭奪到后容易出現問題,具體這里說不清楚,希望明白人跟貼進一步討論之