使用.wait和.notify对象池

我正在尝试在java中创建一个池对象的类。该类开始创建所需的最少数量的对象,当请求开始启动时,每个线程检查是否有可用对象,是否可以创建它因为尚未达到最大值,或者否则它必须等待得到一个。 想法是线程需要同步以获取/创建引擎,但它们可以并行处理(
ProcessWithEngine
方法)。处理可能需要几分钟,显然它正在按我的意愿工作。 问题是,有时当调用
.notify()
并从
.wait()
释放一个线程时,队列有0个项目,这应该是不可能的,因为在
.notify()
之前,添加了一个项目。 可能是什么问题呢? 代码是这样的:
Queue _queue = new Queue();

int _poolMax = 4;
int _poolMin = 1;
int _poolCurrent =0;


public void Process(Object[] parameters) throws Exception
{
    Engine engine = null;

    synchronized(_queue) 
    {
        if(_queue.isEmpty() && _poolCurrent >= _poolMax)
        { 
            _queue.wait();

            // HERE : sometimes _queue.isEmpty() is true at this point.

            engine = (SpreadsheetEngine)_queue.dequeue();

        }
        else if (_queue.isEmpty() && _poolCurrent < _poolMax)
        {               
            engine = CreateEngine();
            _poolCurrent++;
        }
        else
        {               
            engine = (Engine)_queue.dequeue();
        }   
    }

    ProcessWithEngine(engine, parameters);


    // work done
    synchronized(_queue) 
    {
        _queue.enqueue(engine);

        _queue.notify();
    }
}
我已经修好了这样做:
            do
            {
                _queue.wait();

            }
            while(_queue.isEmpty());
但基本上这意味着一个线程正在失去它,它可能意味着稍后超时。     
已邀请:
所有对
.wait()
的调用都必须用
while
循环括起来。拨打
wait()
可以随意唤醒。 根据文档:“在一个参数版本中,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:”     
有了你的解决方案,并不是每个线程都进入无休止的等待()? 正常的习语是这样的:
synchronized(stuff) {
  while (mustWait) 
     wait();
  // do things with stuff
}
另一方面,由于你已经在使用Queue,为什么不把它变成
java.util.concurrent.BlockingQueue
并免费获得并发解决方案呢?     
这有可能至少有两个原因: Justin Waugh指出,虚假的唤醒 另一个线程获取一个锁并在其间调用
dequeue()
- 在第一个线程称为
notify()
并完成其
synchornized
块之后,但在第二个线程实际从其
wait()
醒来之前。这是可能的,因为
synchronized
/
wait()
/
notify()
不保证公平。 因此,
wait()
应始终在循环内使用:
while (_queue.isEmpty())
    _queue.wait();
    

要回复问题请先登录注册