I’m trying to create a class in java that pool objects. The class starts creating the minimum amount of objects required, when the requests start to kick in, every thread checks if there a object available, if it can create it because the maximum has not been reached yet, or if otherwise it has to wait to get one.
The idea is the threads needs to synchronize to get/create an engine, but they can process in parallel (ProcessWithEngine method). The processing could take a couple of minutes, and apparently it’s working as I want.
The problem is, that sometimes when .notify() has been called and a thread is released from the .wait(), the queue has 0 items, and that should be impossible because just before .notify(), an item is added.
What could be the problem?
The code is like this:
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();
}
}
I’ve fixed it doing this:
do
{
_queue.wait();
}
while(_queue.isEmpty());
But basically this means that a thread is losing its turn, and it could mean a timeout later on.
All calls to
.wait()have to be enclosed in awhileloop. Calls towait()can just randomly wake up.Per the documentation: “As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:”