单例(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)的判断,然后争夺锁;结果争夺不到的只能在争夺到后容易出现问题,具体这里说不清楚,希望明白人跟贴进一步讨论之