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