这里错了
        try
        {
          currentThread.wait(timeout);  
        }
        catch (InterruptedException ie)
        {
          ie.printStackTrace();
        }改成        try
        {
          currentThread.sleep(timeout);  
        }
        catch (InterruptedException ie)
        {
          ie.printStackTrace();
        }

解决方案 »

  1.   

    14.3 堵塞
    一个线程可以有四种状态:
    (1) 新(New):线程对象已经创建,但尚未启动,所以不可运行。
    (2) 可运行(Runnable):意味着一旦时间分片机制有空闲的CPU周期提供给一个线程,那个线程便可立即开始运行。因此,线程可能在、也可能不在运行当中,但一旦条件许可,没有什么能阻止它的运行——它既没有“死”掉,也未被“堵塞”。
    (3) 死(Dead):从自己的run()方法中返回后,一个线程便已“死”掉。亦可调用stop()令其死掉,但会产生一个违例——属于Error的一个子类(也就是说,我们通常不捕获它)。记住一个违例的“掷”出应当是一个特殊事件,而不是正常程序运行的一部分。所以不建议你使用stop()(在Java 1.2则是坚决反对)。另外还有一个destroy()方法(它永远不会实现),应该尽可能地避免调用它,因为它非常武断,根本不会解除对象的锁定。
    (4) 堵塞(Blocked):线程可以运行,但有某种东西阻碍了它。若线程处于堵塞状态,调度机制可以简单地跳过它,不给它分配任何CPU时间。除非线程再次进入“可运行”状态,否则不会采取任何操作。14.3.1 为何会堵塞
    堵塞状态是前述四种状态中最有趣的,值得我们作进一步的探讨。线程被堵塞可能是由下述五方面的原因造成的:
    (1) 调用sleep(毫秒数),使线程进入“睡眠”状态。在规定的时间内,这个线程是不会运行的。
    (2) 用suspend()暂停了线程的执行。除非线程收到resume()消息,否则不会返回“可运行”状态。
    (3) 用wait()暂停了线程的执行。除非线程收到nofify()或者notifyAll()消息,否则不会变成“可运行”(是的,这看起来同原因2非常相象,但有一个明显的区别是我们马上要揭示的)。
    (4) 线程正在等候一些IO(输入输出)操作完成。
    (5) 线程试图调用另一个对象的“同步”方法,但那个对象处于锁定状态,暂时无法使用。亦可调用yield()(Thread类的一个方法)自动放弃CPU,以便其他线程能够运行。然而,假如调度机制觉得我们的线程已拥有足够的时间,并跳转到另一个线程,就会发生同样的事情。也就是说,没有什么能防止调度机制重新启动我们的线程。线程被堵塞后,便有一些原因造成它不能继续运行。
      

  2.   

    照你程序的意思不应该用wait(),而应该让当前线程sleep一段时间而且wait()的线程必须被notify()或者notifyAll()否则不会返回runnable state所以,会报错current thread not owner
      

  3.   

    没看你这老长的程序。
    不管你的逻辑如何。
    当你要wait的时候,你必须还在synchronized这个对象。
    比如说,你要obj.wait(), 必须
    synchronized(obj){obj.wait();}
    thread.wait()也不是让thread线程等待,它是让你的当前线程等待thread的信号。总而言之,建议还是好好看看jdk的文档吧。
      

  4.   

    请问obj.wait()和thread.wait()有什么区别?
      

  5.   

    再说你的逻辑,计数是一直递增的。到了最大值后,也不可能再变小。
    既然如此,那个等待线程还等个啥啊?不是单相思嘛?直接throw exception不就完了?
    除非你还有其它的线程去减小计数。
      

  6.   

    没区别,
    thread也就是一个Object.
    看一看Object类的文档就都明白啦。只有让当前线程等待,没有让一个Thread对象等待这码事。
      

  7.   

    to ajoo :那么能否帮忙修改一下增加一个减小计数的线程请不吝赐教,谢谢
      

  8.   

    不过不知道你这减小计数的逻辑是什么样的。就是
    void deref();
    ?
    我这里有一个生产者-消费者的代码,你照自己的需求改改应该就能用:
    public interface Channel{
    public Object get()throws BufferEmptyException;
    //non blocking consume
    public void put(Object obj)throws BufferFullException;
    //non blocking produce
    public Object consume()
    throws InterruptedException;
    //wait indefinitely until available
    public void produce(Object obj)
    throws InterruptedException;
    //wait indefinitely until not full
    public Object consume(long timeout)
    throws ResourceTimeOutException, InterruptedException;

    public void produce(Object val, long timeout)
    throws ResourceTimeOutException, InterruptedException;

    public Object peek()throws BufferEmptyException;
    //non blocking peek
    public boolean isEmpty();
    public boolean isFull();

    public void close();
    public void open();
    public boolean isClosed();
    public void closeSource();
    public void closeSink();
    public void openSource();
    public void openSink();
    public boolean isSourceClosed();
    public boolean isSinkClosed();
    }
    //ChannelBuffer used here does not need to be synchronized.
    //the order of acquiring locks are important to avoid deadlock.
    //our order is always rlock->wlock->thislock
    public final class ChannelImpl implements Channel{
    private final Object rlock = new Object();
    private final Object wlock = new Object();
    private final ChannelBuffer buf;
    private boolean srcoff;
    private boolean sinkoff;
    public final synchronized void open(){
    srcoff = false;
    sinkoff = false;
    }
    public final synchronized void openSource(){
    srcoff = false;
    }
    public final synchronized void openSink(){
    sinkoff = false;
    }
    public final synchronized boolean isClosed(){
    return srcoff&&sinkoff;
    }
    public final void close(){
    synchronized(rlock){
    synchronized(wlock){
    synchronized(this){
    if(!srcoff){
    srcoff = true;
    rlock.notifyAll();
    }
    if(!sinkoff){
    sinkoff = true;
    wlock.notifyAll();
    }
    }
    }
    }
    }
    public final void closeSource(){
    synchronized(rlock){
    synchronized(this){
    if(!srcoff){
    srcoff = true;
    rlock.notifyAll();
    }
    }
    }
    }
    public final void closeSink(){
    synchronized(wlock){
    synchronized(this){
    if(!sinkoff){
    sinkoff = true;
    wlock.notifyAll();
    }
    }
    }
    } public final synchronized boolean isSourceClosed(){
    return srcoff;
    }
    public final synchronized boolean isSinkClosed(){
    return sinkoff;
    } private final synchronized Object _get()
    throws BufferEmptyException{
    if(srcoff)throw new TargetClosedException();
    return buf.get();
    }
    private final synchronized void _put(Object val)
    throws BufferFullException{
    if(sinkoff)throw new TargetClosedException();
    buf.put(val);
    }

    public final Object get()
    throws BufferEmptyException{
    final Object val = _get();
    synchronized(wlock){
    wlock.notify();
    }
    return val;
    } public final void put(Object obj)
    throws BufferFullException{
    _put(obj);
    synchronized(rlock){
    rlock.notify();
    }
    }
    public final synchronized Object peek()
    throws BufferEmptyException{
    return buf.peek();
    }
    public final synchronized boolean isEmpty(){
    return buf.isEmpty();
    }
    public final synchronized boolean isFull(){
    return buf.isFull();
    }
    public final Object consume()
    throws InterruptedException{
    final Object val = _consume();
    synchronized(wlock){
    wlock.notify();
    }
    return val;
    }
    public final void produce(Object obj)
    throws InterruptedException{
    _produce(obj);
    synchronized(rlock){
    rlock.notify();
    }
    }
    public final Object consume(long timeout)
    throws InterruptedException, ResourceTimeOutException{
         if(timeout<=0)
         throw new IllegalArgumentException("timeout should be greater than 0");
    final Object val = _consume(timeout);
    synchronized(wlock){
    wlock.notify();
    }
    return val;
    }
    public final void produce(Object obj, long timeout)
    throws InterruptedException, ResourceTimeOutException{
         if(timeout<=0)
         throw new IllegalArgumentException("timeout should be greater than 0");
    _produce(obj, timeout);
    synchronized(rlock){
    rlock.notify();
    }
    }
    private final Object _consume()
    throws InterruptedException{
    synchronized(rlock){
    for(;;){
    try{
    return _get();
    }
    catch(BufferEmptyException e){
    rlock.wait();
    }
    }
    }
    } private final void _produce(Object val)
    throws InterruptedException{
    synchronized(wlock){
    for(;;){
    try{
    _put(val);
    return;
    }
    catch(BufferFullException e){
    wlock.wait();
    }
    }
    }
    }
    private final Object _consume(long timeout)
    throws InterruptedException, ResourceTimeOutException{
    synchronized(rlock){
    for(long starttime = System.currentTimeMillis();;){
    try{
    return _get();
    }
    catch(BufferEmptyException e){
    rlock.wait(timeout);
        if((System.currentTimeMillis() - starttime) >= timeout){
                         throw new edu.my.util.res.ResourceTimeOutException();
                     }
    }
    }
    }
    } private final void _produce(Object val, long timeout)
    throws InterruptedException, ResourceTimeOutException{
    synchronized(wlock){
    for(long starttime = System.currentTimeMillis();;){
    try{
    _put(val);
    return;
    }
    catch(BufferFullException e){
    wlock.wait(timeout);
    if((System.currentTimeMillis() - starttime) >= timeout){
                         throw new edu.my.util.res.ResourceTimeOutException();
                     }
    }
    }
    }
    } private ChannelImpl(ChannelBuffer buf, boolean srcoff, boolean sinkoff){
    this.buf = buf;
    this.srcoff = srcoff;
    this.sinkoff = sinkoff;
    }
    public static ChannelOwner instance(ChannelBuffer buf){
    return new ChannelImpl(buf, false, false);
    }
    }public interface ChannelBuffer{
    public Object get()throws BufferEmptyException;
    //non blocking consume
    public void put(Object obj)throws BufferFullException;
    //non blocking produce
    public Object peek()throws BufferEmptyException;
    //non blocking peek
    public boolean isEmpty();
    public boolean isFull();
    }代码并不完全。但主要的都在了。
      

  9.   

    好长的程序啊,恐怖减小计数的逻辑?我就是想模拟一下控制实例数量的SingleTon模式能否给个办法简单地模拟一下实例数量的减少呢?我想看看上面我写得那个程序能否正常运行得到一定数量的实例
      

  10.   

    to ajoo大虾:以下是这个程序的最终要求,能否在我上面的程序基础上修改一下,以实现这个目的,谢谢,分数不够请说话Using SingletonPattern.java as a starting point, create a class that manages a fixed number of its own objects. Assume the objects are database connections and you only have a license to use a fixed quantity of these at any one time.
      

  11.   

    呵呵,两百多行也嫌长?(当然,还有几十行的接口定义)你这个设计的逻辑缺陷在于,没有提供一个可靠的释放机制。
    客户怎么释放一个Singleton对象呢?靠finalize()吗?finalize可能根本不运行。
    除非你要求客户显式调用个close()函数。但那样,对客户可是个负担。万一客户忘记调用close()就坏了。
    而且,对一个一般的小对象,限制实例个数并没什么好处。它又不占什么资源。
      

  12.   

    不是作业吧?
    从需求来看,你需要让用户调用一个close()函数。
    而且,也没有要同步等待甚至线程安全的逻辑。
    这不是很简单?class Singleton{
       private final Home home;
       public void close(){
         home.deref();
         //释放其它昂贵的资源。
       }
       
    }
    class SingletonHome implements Home{
       public void deref(){--ref;}
       public Singleton get(){if(ref>=max)throw new TooManyInstancesException(); ++ref; return new Singleton(this);}
       private final int max;
       private int ref;
    }然后就
    SingletonHome home = new SingletonHome();
    Singleton s1 = home.get();home.get();
    Singleton s2 = home.get();
    s1.close();
    s2.close();
      

  13.   

    唉,大哥你误会了那段英文不是什么作业啊是Bruce Eckel 的 Thinking In Pattern的练习题
      

  14.   

    你是说我刚才随便写的demo吧?
    你的需求里根本没有线程安全啊。再说,要安全还不容易?加上synchronized不就完了?
      

  15.   

    修改了一下,基本实现了增加和减少的功能,但是在线程控制上,会出现死锁的情况package org.javaresearch.jfml.designpatterns;
    public class SingletonPattern2
    {
      public static void main(String[] args)
      {
        Singleton2 s = Singleton2.newInstance();
        
        new OpenThread("open thread").start();
        new CloseThread("close thread").start();
      }
    }
    final class OpenThread extends Thread
    {
      public OpenThread(String str)
      {
        super(str);
      }
      
      public void run()
      {
        Singleton2 s = Singleton2.newInstance();
        
        int count = 0;
        while (count < 10)
        {
          s.open();
          count ++;
        }
      }
    }
    final class CloseThread extends Thread
    {
      public CloseThread(String str)
      {
        super(str);
      }
      
      public void run()
      {
        Singleton2 s = Singleton2.newInstance();
        
        int count = 0;
        while (count < 10)
        {
          s.close();
          count ++;
        }
      }
    }
    final class Singleton2
    {
      public static Singleton2 instance = new Singleton2();
      
      public final int maxInstances = 10;
      public int currentInstances;
      
      public static Singleton2 newInstance()
      {
        if ( null == instance )
        {
          return new Singleton2();
        }
        
        return instance;
      }
      
      private Singleton2()
      {
      }
      
      public synchronized void open() throws ReferenceOverAgeException
      {
        if ( currentInstances < maxInstances )
        {
          ++ currentInstances;
          System.out.println("current references are "+currentInstances);
        }
        else
        {
          try
          {
            wait();
          }
          catch (InterruptedException e)
          {
            e.printStackTrace();
          }
        }
        
        notifyAll();
      }
      
      public synchronized void close() throws ReferenceShortAgeException
      {
        if ( currentInstances > 0 )
        {
          -- currentInstances;
          System.out.println("current references are "+currentInstances);
        }
        else
        {
          try
          {
            wait(); 
          }
          catch (InterruptedException e)
          {
            e.printStackTrace();
          }
        }
        
        notifyAll();
      }
    }
      

  16.   

    上面的程序中,当
      public void run()
      {
        Singleton2 s = Singleton2.newInstance();
        
        int count = 0;
        while (count < 10)
        {
          s.close();
          count ++;
        }
      }count < 10中,当10改成了大于instancesMax的数值后,程序就会出现死锁
    如何处理才能避免这个死锁,而且又不影响程序的运行(也就是说不允许open一次,然后必须close一次这样的控制。open和close必须是自由的)