java - 使用 .wait 和 .notify 进行对象池

标签 java multithreading synchronization 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() 可以随机唤醒。

根据documentation :“与单参数版本一样,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:”

关于java - 使用 .wait 和 .notify 进行对象池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5622428/

相关文章:

java - obj.notify() 似乎不起作用

java - 这种 EBNF 方法是否正确?

multithreading - 字节码/中间语言/编译器后端的可移植多线程支持?

c++ - pthread_exit 与 posix 线程中的返回

c# - 具有 IsBackground 的 Lambda 线程

java - java中同步块(synchronized block)之后的代码

java - 如何从方法返回数组列表

java - 为什么程序员说 "pass by reference"真的是 "passing references by value?"为什么这很重要?

java - 在 Guice 注入(inject)器内运行,@Injects 在 `new` -ed 类上不受尊重

ruby-on-rails - 如何防止许多 sidekiq 作业超过 API 调用限制