关于多例模式-from单例模式

第二种形式:

public class Singleton {
  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     
  //使用时生成实例,提高了效率!
  if (instance==null)
    instance=new Singleton();
  return instance;   }

}


使用Singleton.getInstance()可以访问单态类。

上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。

注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。

------------
以上引用jdon.com
请问如何写一个测试例子,能够证明可以生成多例模式,我现在某种情况下需要多例!也就是大多数情况需要利用单例模式调用资源,但是如果资源被占用的时候,需要从新生成一个对象,去掉synchronized可以?能不能给个测试的例子!

现在的具体情况是这样的,我有点被单例模式搞糊涂了。
我有一个Class A的类,这个类每个page都会用到。

所以我希望用单例模式防止过度重建对象。
现在的问题是:
1、如果已经有page使用的时候,要从新new一个。
2、如果没有page没有在用的时候,可以从新使用。

我怎么感觉好像需要对象池来管理了,简单的单例模式不知道是不是可以?

是的,需要使用池模式来解决,池中每个实例是单例。

池中每个实例是单例。这句不准确,你所要的就是object pool

有没有简单的对象池管理框架,我不想用EJB的
另外,能不能测试一个例子,证明你的多例模式的存在?
static的应该只能存在一个实例呀

你的情况是很多page都会用到这个类,并且在整个周期中,该类可以有多个实例,所以从根本上你选择单例模式是错误的。
如果想重用那就建一个对象池,在池中对这些对象的生长和销毁进行处理。

简单的写了一些多例模式的代码,不一定正确啊,思路是
每次要用到Cat类时,就用getInstance()去取,这里定义
最多有10个实例,如果发现Vector中没有实例,则创建一个
并使用,同时用setIsUse()方法设置isUse为true,使用完
毕就设置该变量为true(这只是简单的表示,不一定好)。
如果实例存在,则判断是否被使用,如果没有则返回,如果
被使用,则继续判断Vector中下一个实例,如果10个实例都
被使用,则返回null,让新的page等待或者进行别的处理。


public class Cat {
private static Vector instance= new Vector(10);
//表示该实例是否被使用
private boolean isUse = false;
private Cat() {
}
static public synchronized Cat getInstance(){
Cat obj = null;
for(int i = 0; i < instance.size();i++){
obj = (Cat)instance.elementAt(i);
if(obj==null){
obj = new Cat();
instance.setElementAt(obj,i);
return obj;
}
else if(!obj.getIsUse()){
return obj;
}

}
//返回null表示目前对象池里没有空闲的对象
return null;
}

public boolean getIsUse(){
return isUse;
}
public void setIsUse(boolean isUse){
this.isUse = isUse;
}
}

按照你的代码,如果我在使用Cat对象的时候每次都要先setuse=ture
页面结束以后再setuse=false,这样不是很好.

不过你给我了一些思路,我想没必要用单例模式,自己建立一个管理池
设定大小以后就行轮循

public class STPoolManager {
private static final int loop = 10;
private static int loopAt = 0;
private static Vector instance = new Vector(loop);
private STPoolManager() {
for(int i=0 ; i<loop ; i++){
SuperTemplate obj = new SuperTemplate();
instance.setElementAt(obj,i);
}
}

public static synchronized SuperTemplate factory(){
SuperTemplate obj = (SuperTemplate)instance.get(loopAt);
if(loopAt == loop-1)
loopAt = 0;
else
loopAt++;
return obj;
}

}



public class STPoolManager {
private static final int loop = 10;
private static int loopAt = 0;
private static Vector instance = new Vector(loop);
private STPoolManager() {
for(int i=0 ; i<loop ; i++){
SuperTemplate obj = new SuperTemplate();
instance.setElementAt(obj,i);
}
}

public static synchronized SuperTemplate factory(){
SuperTemplate obj = (SuperTemplate)instance.get(loopAt);
if(loopAt == loop-1)
loopAt = 0;
else
loopAt++;
return obj;
}

}

不过还是没有解决资源在使用中的情况!

我看了你的代码之后,觉得你好像没有理解我的本意。
isUse的用法正如我自己提到的,只是一个方便的表示,
你可以考虑其他的表示,既然用到这个类,你肯定要执行某些逻辑
在执行这些逻辑的时候,开头和结束可以考虑占用和释放Cat类的实例,
并不一定要在page的代码里来操作啊。
至于你怎么占用和释放,采取什么方式就结合你自己的实际场景采取
相应的措施。

主要的关于Cat的资源控制是在那个静态方法里面。

其实你这样写,还是没办法避免当你的loopAt已经到10了,instance[0]却还没有释放,还是需要等待啊。

另一方面,防止过度的创建对象,并不一定意味着已经创建的对象要一直的存在,可以定义一个集合,规定同时最多可以有一定数量的对象存在,当用完这个对象的时候,就把它从集合中remove掉,从而可以创建相应数量的新对象。

如果是池的话,肯定是需要保持一定数量的操作.
不过我现在考虑了一下,如果创建对象不怎么占用
系统时间的话,也许new一个就可以了,只不过java
的垃圾回收不知道是如何进行的,如果很慢的话,那
么在一定时间内就会有大量的对象产生,就有必要
控制如何创建对象了.

java的垃圾机制是基于线程的,是优先级最低的线程,(为0)
所以很久才会回收垃圾。(读<<java夜未眼>>得知