在java中使用轮询不好吗?

xpcnnkqh  于 2021-07-13  发布在  Java
关注(0)|答案(7)|浏览(299)

我有好几个 ArrayLists 作为数据队列工作。每个队列都链接到一个单独的线程,该线程检查 ArrayList 里面有一些数据。

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

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

我在嵌入式系统编程中也做过类似的事情,但是在java中使用它安全吗?我们担心的是,在循环非常快的情况下,循环会造成过程功耗的浪费。
可以通过添加 Thread.sleep(100) 每100毫秒检查一次,然后再检查一次-响应时间变慢。
问题是-我需要补充睡眠还是我不应该担心这个?
有没有关于更安全/更好的系统来检查阵列中的新数据的建议?

afdcj2ne

afdcj2ne1#

arraylist不是线程安全的集合,因此如果一个线程向列表中添加数据,而另一个线程尝试从同一列表中检索数据,则不能保证另一个线程将看到添加的元素。
像你描述的那样忙着等待会不必要地消耗cpu资源。
既然你似乎需要排队,为什么不用一个,比如 ArrayBlockingQueue . 它有一个 take 方法,该方法将在不消耗cpu周期的情况下进行阻塞,直到某个项被添加到队列中。它是线程安全的。

ffx8fchx

ffx8fchx2#

除非您需要等待的时间非常短,从而使上下文切换过于昂贵,否则我不会使用旋转。它毫无理由地浪费cpu周期。
你应该使用 wait/notify 或者其他一些信号机制来挂起线程,并仅在必要时唤醒它。
关于更高级的构造,生产者-消费者模式有专门的数据结构,比如blockingqueue(选择一个实现):
一种队列,它还支持在检索元素时等待队列变为非空,在存储元素时等待队列中的空间变为可用的操作。

mw3dktmi

mw3dktmi3#

不如使用Java5中发布的阻塞队列之类的东西。我认为这是建议现在超过等待/通知,这可能会变得相当复杂。我用过,效果很好。
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/blockingqueue.html

knpiaxh1

knpiaxh14#

不使用arraylist,您可以使用并发集合,例如arrayblockingqueue

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

在另一个地方,当你排队时,你只需要做一个

theQueue.add(theElement);

等待对象的线程将“休眠”,直到有一个元素。add方法将唤醒消费线程。
你可以在这里阅读更多关于这门课的内容:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/arrayblockingqueue.html

1rhkuytd

1rhkuytd5#

java.lang.ArrayList 完全不是线程安全的。出于排队的目的,这是很好的使用 BlockingQueue . 如果队列为空而不消耗cpu,它将阻止线程调用。你可以用 ArrayBlockingQueue 或者 LinkedBlockingQueue 或其他队列实现。
甚至你也可以用 wait and notifyAll 但它总是被推荐使用 BlockingQueue .

whhtz7ly

whhtz7ly6#

如果没有睡眠,线程将以最快的速度循环并访问arraylist,可能大多数情况下没有任何结果。
我建议实现一个侦听器/观察者模式。如果可以,让填充arraylist的生产者在更改时通知相应的线程。因此,您将从轮询行为转变为推送行为。
不确定这在您的体系结构中是否可行,但需要对您的系统进行进一步的解释。

gev0vcfq

gev0vcfq7#

什么是投票,有什么问题吗?
反复测试一个条件直到它变为真的过程称为轮询。
轮询通常借助于循环来实现,以检查特定条件是否为真。如果这是真的,一定要采取行动。这会浪费很多cpu周期,并使实现效率低下。例如,在一个经典的排队问题中,一个线程正在生成数据,而另一个线程正在消耗数据。
java多线程如何解决这个问题?
为了避免轮询,java使用了三种方法,即, wait() , notify() 以及 notifyAll() .
所有这些方法都属于 Object 最后一节课,这样所有的课都有。它们只能在同步块中使用。
wait()—它告诉调用线程放弃锁并进入睡眠状态,直到其他线程进入同一监视器并调用 notify() .
notify()-它唤醒一个调用 wait() 在同一个物体上。需要注意的是 notify() 实际上不会放弃对资源的锁定。
notifyall()-它唤醒所有调用 wait() 在同一个物体上。 ArrayList 不是线程安全集合。使用 ArrayBlockingQueue .
类arrayblockingqueue

相关问题