繁体   English   中英

Java ArrayBlockingQueue 阻塞直到队列中有东西

[英]Java ArrayBlockingQueue blocking until the queue has something in it

我有许多不同的套接字连接到我的代码,每个套接字都在独立线程上侦听。 在将对象传递到这些套接字中的任何一个之前,时间可能会过去。 所以我有一个基本上永远运行的 while(running) 循环。

然后为了同步所有不同的线程,我有一个 ArrayBlockingQueue。 每当套接字/线程组合接收到一个对象时,我就会将该对象添加到 ArrayBlockingQueue(因为它会自动为我同步)。 然后在 while(running) 代码中,我删除对象并处理它。

问题是处理器在那个 while(running) 循环中变得疯狂......理想情况下,我想阻止开始处理所有对象,直到 ArrayBlockingQueue 实际上有一些东西要处理,希望处理器不会继续运行。

你知道这是否可能?

这是我当前的代码,它导致处理器旋转并浪费周期......

@Override
    public void run()
    {
        while(running)
        {
            while(messageQueue.size() > 0)
            {
                Object o = messageQueue.remove();
            }
        }
    }

这是我想要的...

@Override
    public void run()
    {
        while(running)
        {
            messageQueue.BlockUntilSomethingInHere();

            while(messageQueue.size() > 0)
            {
                Object o = messageQueue.remove();
            }
        }
    }

请注意,在执行messageQueue.remove()之前检查messageQueue.size() > 0被称为check-then-act反模式。 如果您有多个线程移除元素,则有可能条件在检查和后续操作之间发生变化,从而导致异常。

只需使用take()而不是remove()

while(running) try {
    Object o = messageQueue.take();
    // ...
} catch(InterruptedException ex) {
    // (running) will be checked before the next loop iteration
}

take()将等待元素变为可用。 要在队列为空时结束此循环,您必须将running设置为false并中断线程。 如果无法中断,您可以使用定时等待:

while(running) try {
    Object o = messageQueue.poll​(1, TimeUnit.SECOND);
    if(o != null) {
        // ...
    }
}
catch(InterruptedException ex) {
  // (running) will be checked before the next loop iteration
}

然后,可能需要一秒钟,直到等待空队列的线程对running设置为false做出反应(请注意将running声明为volatile )。 可以更改超时时间,以权衡响应能力和 CPU 消耗。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM