Java ArrayBlockingQueue会阻塞,直到队列中有内容。

huangapple go评论82阅读模式
英文:

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();
        }
    }
}
英文:

I have a number of different sockets connecting to my code that are all each listening on independent threads. Time may go by before an object is passed to any of these sockets. So I have a while(running) loop that runs basically forever.

Then to synchronize all the different threads, I have an ArrayBlockingQueue. Whenever a socket/thread combo receives an object, I then add that object to the ArrayBlockingQueue (since it is automatically synchronized for me). Then in the while(running) code, I remove the object and process it.

The problem is that the processor goes crazy in that while(running) loop... Ideally I would like to block on starting to process all the objects until the ArrayBlockingQueue actually has something to process in hopes that the processor doesn't keep running.

Do you know if this is possible?

Here is my current code that causes the processor to spin up and waste cycles...

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

Here is what I would like...

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

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

答案1

得分: 2

请注意,在执行messageQueue.remove()之前检查messageQueue.size() > 0被称为检查然后操作反模式。如果有多个线程在移除元素,则在检查和随后的操作之间可能会导致条件发生更改,从而引发异常。

只需使用take()替代remove()

while(running) try {
    Object o = messageQueue.take();
    // ...
} catch(InterruptedException ex) {
    // 下一次循环迭代之前将会检查(running)
}

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

while(running) try {
    Object o = messageQueue.poll(1, TimeUnit.SECONDS);
    if(o != null) {
        // ...
    }
}
catch(InterruptedException ex) {
  // 下一次循环迭代之前将会检查(running)
}

然后,线程在等待空队列时对设置为falserunning做出反应最多可能需要一秒钟(请确保将running声明为volatile)。可以更改超时时间,以在响应性和CPU消耗之间进行权衡。

英文:

Note that checking for messageQueue.size() > 0 before performing messageQueue.remove() is known as the check-then-act antipattern. If you have more than one thread removing elements, there’s the possibility that the condition changes between the check and the subsequent action, leading to an exception.

Just use take() instead of remove():

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

take() will wait until an element becomes available. To end this loop when the queue is empty, you have to set running to false and interrupt the thread. If interruption is not possible, you can use timed wait:

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
}

Then, it may take up to a second until the thread waiting on an empty queue will react on running set to false (mind to declare running as volatile). The timeout can be changed, to trade off responsiveness and CPU consumption.

huangapple
  • 本文由 发表于 2020年10月19日 09:42:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/64420086.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定