Java 对象池与.wait和.notify
我正在尝试用java创建一个类来池对象。该类开始创建所需的最小数量的对象,当请求开始启动时,每个线程检查是否有可用的对象,是否由于尚未达到最大值而可以创建该对象,或者是否必须等待获得一个对象 其思想是线程需要同步以获取/创建引擎,但它们可以并行处理(Java 对象池与.wait和.notify,java,multithreading,synchronization,wait,notify,Java,Multithreading,Synchronization,Wait,Notify,我正在尝试用java创建一个类来池对象。该类开始创建所需的最小数量的对象,当请求开始启动时,每个线程检查是否有可用的对象,是否由于尚未达到最大值而可以创建该对象,或者是否必须等待获得一个对象 其思想是线程需要同步以获取/创建引擎,但它们可以并行处理(ProcessWithEnginemethod)。处理过程可能需要几分钟,而且很明显,它正在按照我的要求工作 问题是,有时当调用.notify()并从.wait()中释放线程时,队列中有0个项目,这应该是不可能的,因为就在.notify()之前添加了
ProcessWithEngine
method)。处理过程可能需要几分钟,而且很明显,它正在按照我的要求工作
问题是,有时当调用.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();
}
}
synchronized(stuff) {
while (mustWait)
wait();
// do things with stuff
}
但基本上这意味着线程正在失去轮次,这可能意味着稍后超时。对.wait()
的所有调用都必须包含在while
循环中。对wait()
的调用可以随机唤醒
根据:“在单参数版本中,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:”对.wait()
的所有调用都必须在while
循环中包含。对wait()
的调用可以随机唤醒
根据:“在单参数版本中,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:”对于您的解决方案,不是每个线程都会进入无休止的等待() 通常的习语是这样的:
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();
}
}
synchronized(stuff) {
while (mustWait)
wait();
// do things with stuff
}
另一方面,既然您已经在使用队列,为什么不将其设置为
java.util.concurrent.BlockingQueue
,并免费获得一个并发解决方案?使用您的解决方案,不是每个线程都会进入无止境的等待()
通常的习语是这样的:
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();
}
}
synchronized(stuff) {
while (mustWait)
wait();
// do things with stuff
}
另一方面,既然您已经在使用队列,为什么不将其设置为
java.util.concurrent.BlockingQueue
并免费获得并发解决方案呢?至少有两个原因:
- 贾斯汀·沃(Justin Waugh)指出的虚假唤醒
- 另一个线程获取一个锁并在其间调用
——在第一个线程调用dequeue()
并完成其notify()
块之后,但在第二个线程实际从其synchornized
wait()唤醒之前。这是可能的,因为
/synchronized
/wait()
不能保证公平性notify()
wait()
:
while (_queue.isEmpty())
_queue.wait();
这可能至少有两个原因:
- 贾斯汀·沃(Justin Waugh)指出的虚假唤醒
- 另一个线程获取一个锁并在其间调用
——在第一个线程调用dequeue()
并完成其notify()
块之后,但在第二个线程实际从其synchornized
wait()唤醒之前。这是可能的,因为
/synchronized
/wait()
不能保证公平性notify()
wait()
:
while (_queue.isEmpty())
_queue.wait();
你确定你没有使用空引擎吗?如果(engine!=null)那么{u queue.enqueue(engine);\u queue.notify()}请尝试在“work done”上插入此检查。是的,实际上,被注释的那一行以前是实际的一行,我可以检查队列是否为空。可能读者和作者模式可以解决您的问题:@vtorola-您能提供完整的代码吗,理解目的的需要。您确定您没有使用空引擎吗?如果(engine!=null)那么{u queue.enqueue(engine);\u queue.notify()}请尝试在“work done”上插入此检查。是的,实际上,被注释的那一行以前是实际的一行,我可以检查队列是否为空。可能读者和作者模式可以解决您的问题:@vtorola-您能提供完整的代码吗,理解目的的需要“虚假的觉醒”?好极了我将把它放在一个线程中,启动一个有很多线程的测试,看看会发生什么。万分感谢,“虚假的觉醒”?好极了我将把它放在一个线程中,启动一个有很多线程的测试,看看会发生什么。非常感谢。我刚做了个循环。我无法使用BlockinQueue,因为它在我的环境中不存在。该环境是SAP的一个旧JavaIDE,它没有通用的或任何新的,我认为是Java1!愿原力与你同在;-)我只是做了个循环。我无法使用BlockinQueue,因为它在我的环境中不存在。该环境是SAP的一个旧JavaIDE,它没有通用的或任何新的,我认为是Java1!愿原力与你同在;-)所有线程逻辑都包含在该方法中,队列仅在该方法中使用。所以这可能是第一个选择。我现在正在做一个测试。谢谢。@vtortola:但方法被许多线程调用,对吗?因此,新的调用可能会在两个方法之间发生。所有线程逻辑都包含在该方法中,并且队列仅在该方法中使用。所以这可能是第一个选择。我现在正在做一个测试。谢谢。@vtortola:但方法被许多线程调用,对吗?因此,新的呼叫可能会在两者之间发生。