在 Java 中使用轮询很糟糕吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12159564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 07:50:47  来源:igfitidea点击:

Is it bad to use polling in Java?

javamultithreading

提问by Arturs Vancans

I have several ArrayListswhich work as queues of data. Each of the queues is linked to an individual threadwhich checks if that ArrayListhas some data in it.

我有几个ArrayLists用作数据队列。每个队列都链接到一个单独的线程,该线程检查其中是否ArrayList有一些数据。

 while (array.size == 0) {
    // nothing
 }

 // do stuff with one element of the array
 // remove element from array
 // and call the loop again

I have done similar things in embedded system programming, but is it safe to use this in Java? The concern is about process power waste by iterating around that while loop very fast.

我在嵌入式系统编程中做过类似的事情,但是在 Java 中使用它安全吗?关注的是通过非常快速地迭代 while 循环来浪费处理能量。

It could be solved by adding Thread.sleep(100)and check every 100ms, but then again - slower response time.

它可以通过Thread.sleep(100)每 100 毫秒添加和检查一次来解决,但又一次 - 响应时间变慢。

The question is - do I need to add that sleep or I shouldn't be concerned about that?

问题是 - 我需要添加睡眠还是我不应该担心?

Any suggestions on safer/better system to check for new data in arrays?

关于更安全/更好的系统来检查阵列中的新数据的任何建议?

回答by assylias

ArrayList is not a thread safe collection, so if one thread adds data to your list, and another thread tries to retrieve data from the same list, you have no guarantee that the other thread will ever see the added elements.

ArrayList 不是线程安全的集合,因此如果一个线程向您的列表添加数据,而另一个线程尝试从同一列表中检索数据,则您无法保证另一个线程会看到添加的元素。

And busy waiting like what you describe consumes cpu resources unnecessarily.

像您描述的那样忙于等待会不必要地消耗 cpu 资源。

Since you seem to need a queue, why don't you use one, like ArrayBlockingQueue. It has a takemethodwhich will block, without consuming CPU cycles, until an item gets added to the queue. And it is thread safe.

既然您似乎需要一个队列,为什么不使用一个队列,例如ArrayBlockingQueue. 它有一个take方法,它会在不消耗 CPU 周期的情况下阻塞,直到一个项目被添加到队列中。它是线程安全的。

回答by Tudor

Unless the time that you need to wait is very very short, thus making a context switch too expensive, I would not use spinning. It definitely wastes CPU cycles for no good reason.

除非您需要等待的时间非常短,从而使上下文切换过于昂贵,否则我不会使用旋转。它肯定会无缘无故地浪费 CPU 周期。

You should use wait/notifyor some other signaling mechanism to suspend the thread and wake it up only when necessary.

您应该使用wait/notify或 其他一些信号机制来暂停线程并仅在必要时将其唤醒。

Going to more advanced constructs, there are specialized data structures for producer-consumer patterns, like BlockingQueue(choose an implementation):

转到更高级的构造,生产者-消费者模式有专门的数据结构,例如BlockingQueue(选择一个实现):

A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.

一个 Queue 额外支持在检索元素时等待队列变为非空的操作,并在存储元素时等待队列中有可用空间。

回答by RNJ

How about using somehting like blocking queue that was released in java 5. I think this is recommended now over wait/notify which can get quite complicated. I've used it and it works well.

使用诸如 java 5 中发布的阻塞队列之类的东西如何。我认为现在推荐使用这种方法而不是等待/通知,这会变得非常复杂。我已经使用过它并且效果很好。

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

回答by Subhrajyoti Majumder

java.lang.ArrayListis not thread safe at all. For queuing purpose, it's good to use BlockingQueue. It blocks thread call if queue is empty without consuming cpu. You can use ArrayBlockingQueueor LinkedBlockingQueueor other queue implementation according to your need.

java.lang.ArrayList根本不是线程安全的。出于排队目的,最好使用BlockingQueue. 如果队列为空,它会阻止线程调用而不消耗 cpu。您可以根据需要使用ArrayBlockingQueueLinkedBlockingQueue或其他队列实现。

Even you can implement it with wait and notifyAllbut it is always recommend to use BlockingQueue.

即使您可以使用wait and notifyAll它来实现它,但始终建议使用BlockingQueue.

回答by anizzomc

Instead of using ArrayList, you can use a Concurrent collection, lets say, for example an ArrayBlockingQueue

除了使用 ArrayList,您还可以使用 Concurrent 集合,例如 ArrayBlockingQueue

ArrayBlockingQueue<YourObject> theQueue;
while(true) {
  YourObject o = theQueue.take();
 //process your object
}

In the other place, where you fill your queue, you just do an

在另一个地方,你填满你的队列,你只需做一个

theQueue.add(theElement);

The thread that is waiting for objects will "sleep" until there is an element. The add method will wake up the consuming thread.

等待对象的线程将“休眠”,直到有一个元素。add 方法将唤醒消费线程。

You can read more about this class here: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ArrayBlockingQueue.html

您可以在此处阅读有关此类的更多信息:http: //docs.oracle.com/javase/6/docs/api/java/util/concurrent/ArrayBlockingQueue.html

回答by roottraveller

What is Polling and what are problems with it?

什么是轮询?它有什么问题?

The process of testing a condition repeatedly till it becomes true is known as polling.

重复测试条件直到它变为真的过程称为轮询。

Polling is usually implemented with the help of loops to check whether a particular condition is true or not. If it is true, certain action is taken. This waste many CPU cycles and makes the implementation inefficient. For example, in a classic queuing problem where one thread is producing data and other is consuming it.

轮询通常在循环的帮助下实现,以检查特定条件是否为真。如果为真,则采取某些行动。这会浪费许多 CPU 周期并使实现效率低下。例如,在一个经典的排队问题中,一个线程正在生成数据而另一个线程正在使用它。

How Java multi threading tackles this problem?

Java 多线程如何解决这个问题?

To avoid polling, Java uses three methods, namely, wait(), notify()and notifyAll().

为了避免轮询,Java 使用了三种方法,即wait()notify()notifyAll()

All these methods belong to Objectclass as final so that all classes have them. They must be used within a synchronized block only.

所有这些方法都属于Object最终类,以便所有类都拥有它们。它们只能在同步块中使用。

wait()-It tells the calling thread to give up the lock and go to sleep until some other thread enters the same monitor and calls notify().

wait()- 它告诉调用线程放弃锁定并进入睡眠状态,直到其他线程进入同一个监视器并调用notify().

notify()-It wakes up one single thread that called wait()on the same object. It should be noted that calling notify()does not actually give up a lock on a resource.

notify()- 它唤醒一个调用wait()同一个对象的线程。需要注意的是,调用notify()实际上并没有放弃对资源的锁定。

notifyAll()-It wakes up all the threads that called wait()on the same object.

notifyAll()- 它唤醒所有调用wait()同一个对象的线程。

ArrayListis not a thread safe collection. Use ArrayBlockingQueue.

ArrayList不是线程安全的集合。使用ArrayBlockingQueue.

Class ArrayBlockingQueue

ArrayBlockingQueue 类

回答by Tobias N. Sasse

Without a sleep your threads are going to loop as fast as they can and access the ArrayList, probably most times without any outcome.

如果没有睡眠,您的线程将尽可能快地循环并访问 ArrayList,可能大多数时候没有任何结果。

I'd recommend to implement a Listener/Observer Pattern. If you can, have the producer which fills the ArrayList notify the appropriate threads on changes. Thus you would shift from a polling behaviour to a push behaviour.

我建议实施侦听器/观察器模式。如果可以,让填充 ArrayList 的生产者通知适当的线程更改。因此,您将从轮询行为转变为推送行为。

Not sure whether that is doable within your architecture, would need further explanations on your system though.

不确定这在您的架构中是否可行,但需要对您的系统进行进一步解释。