我有几个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毫秒检查一次,然后再次检查 - 响应时间变慢。
问题是 - 我是否需要添加睡眠,或者我不应该关注它?
有关更安全/更好的系统检查数组中新数据的任何建议吗?
答案 0 :(得分:53)
ArrayList不是线程安全集合,因此如果一个线程将数据添加到列表中,而另一个线程尝试从同一列表中检索数据,则无法保证其他线程将看到添加的元素。
忙着等你描述的东西不必要地消耗cpu资源。
由于您似乎需要一个队列,为什么不使用一个队列,例如ArrayBlockingQueue
。它有一个take
method,它会在不消耗CPU周期的情况下阻塞,直到项目被添加到队列中。它是线程安全的。
答案 1 :(得分:11)
除非您需要等待的时间非常短,因此上下文切换太昂贵,我不会使用旋转。它绝对没有充分的理由浪费CPU周期。
您应该使用wait/notify
或其他一些信号机制暂停线程并仅在必要时将其唤醒。
对于更高级的构造,生成器 - 消费者模式有专门的数据结构,如BlockingQueue(选择实现):
另外支持等待队列的操作的队列 在检索元素时变为非空,并等待空间 存储元素时在队列中可用。
答案 2 :(得分:2)
如何使用在java 5中发布的阻塞队列之类的东西。我认为现在建议使用wait / notify,这会变得相当复杂。我用过它并且效果很好。
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
答案 3 :(得分:1)
java.lang.ArrayList
根本不是线程安全的。出于排队目的,最好使用BlockingQueue
。如果队列为空而不消耗cpu,它会阻止线程调用。您可以根据需要使用ArrayBlockingQueue
或LinkedBlockingQueue
或其他队列实施。
即使您可以使用wait and notifyAll
实施它,但始终建议您使用BlockingQueue
。
答案 4 :(得分:1)
您可以使用Concurrent集合,例如ArrayBlockingQueue
,而不是使用ArrayList。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
答案 5 :(得分:0)
没有睡眠,您的线程将尽可能快地循环并访问ArrayList,可能大多数时候没有任何结果。
我建议实现一个Listener / Observer模式。如果可以的话,让填充ArrayList的生产者通知相应的线程进行更改。因此,您将从轮询行为转变为推送行为。
不确定您的架构中是否可行,但需要对您的系统进行进一步说明。
答案 6 :(得分:0)
什么是投票?问题是什么?
反复测试一个条件直到它变为真的过程被称为轮询。
轮询通常在循环的帮助下实现,以检查特定条件是否为真。如果确实如此,则采取某些行动。这浪费了许多CPU周期并使实现效率低下。 例如,在一个经典的排队问题中,一个线程正在生成数据而另一个正在使用它。
Java多线程如何解决这个问题?
为避免轮询,Java使用三种方法,即wait()
,notify()
和notifyAll()
。
所有这些方法都属于Object
类,因此所有类都有它们。它们必须仅在同步块中使用。
wait() - 它告诉调用线程放弃锁定并进入休眠状态,直到某个其他线程进入同一个监视器并调用notify()
。
notify() - 唤醒在同一对象上调用wait()
的单个线程。应该注意的是,调用notify()
实际上并没有放弃对资源的锁定。
notifyAll() - 唤醒在同一对象上调用wait()
的所有线程。
ArrayList
不是线程安全的集合。使用ArrayBlockingQueue
。