我有好几个 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毫秒检查一次,然后再检查一次-响应时间变慢。
问题是-我需要补充睡眠还是我不应该担心这个?
有没有关于更安全/更好的系统来检查阵列中的新数据的建议?
7条答案
按热度按时间afdcj2ne1#
arraylist不是线程安全的集合,因此如果一个线程向列表中添加数据,而另一个线程尝试从同一列表中检索数据,则不能保证另一个线程将看到添加的元素。
像你描述的那样忙着等待会不必要地消耗cpu资源。
既然你似乎需要排队,为什么不用一个,比如
ArrayBlockingQueue
. 它有一个take
方法,该方法将在不消耗cpu周期的情况下进行阻塞,直到某个项被添加到队列中。它是线程安全的。ffx8fchx2#
除非您需要等待的时间非常短,从而使上下文切换过于昂贵,否则我不会使用旋转。它毫无理由地浪费cpu周期。
你应该使用
wait/notify
或者其他一些信号机制来挂起线程,并仅在必要时唤醒它。关于更高级的构造,生产者-消费者模式有专门的数据结构,比如blockingqueue(选择一个实现):
一种队列,它还支持在检索元素时等待队列变为非空,在存储元素时等待队列中的空间变为可用的操作。
mw3dktmi3#
不如使用Java5中发布的阻塞队列之类的东西。我认为这是建议现在超过等待/通知,这可能会变得相当复杂。我用过,效果很好。
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/blockingqueue.html
knpiaxh14#
不使用arraylist,您可以使用并发集合,例如arrayblockingqueue
在另一个地方,当你排队时,你只需要做一个
等待对象的线程将“休眠”,直到有一个元素。add方法将唤醒消费线程。
你可以在这里阅读更多关于这门课的内容:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/arrayblockingqueue.html
1rhkuytd5#
java.lang.ArrayList
完全不是线程安全的。出于排队的目的,这是很好的使用BlockingQueue
. 如果队列为空而不消耗cpu,它将阻止线程调用。你可以用ArrayBlockingQueue
或者LinkedBlockingQueue
或其他队列实现。甚至你也可以用
wait and notifyAll
但它总是被推荐使用BlockingQueue
.whhtz7ly6#
如果没有睡眠,线程将以最快的速度循环并访问arraylist,可能大多数情况下没有任何结果。
我建议实现一个侦听器/观察者模式。如果可以,让填充arraylist的生产者在更改时通知相应的线程。因此,您将从轮询行为转变为推送行为。
不确定这在您的体系结构中是否可行,但需要对您的系统进行进一步的解释。
gev0vcfq7#
什么是投票,有什么问题吗?
反复测试一个条件直到它变为真的过程称为轮询。
轮询通常借助于循环来实现,以检查特定条件是否为真。如果这是真的,一定要采取行动。这会浪费很多cpu周期,并使实现效率低下。例如,在一个经典的排队问题中,一个线程正在生成数据,而另一个线程正在消耗数据。
java多线程如何解决这个问题?
为了避免轮询,java使用了三种方法,即,
wait()
,notify()
以及notifyAll()
.所有这些方法都属于
Object
最后一节课,这样所有的课都有。它们只能在同步块中使用。wait()—它告诉调用线程放弃锁并进入睡眠状态,直到其他线程进入同一监视器并调用
notify()
.notify()-它唤醒一个调用
wait()
在同一个物体上。需要注意的是notify()
实际上不会放弃对资源的锁定。notifyall()-它唤醒所有调用
wait()
在同一个物体上。ArrayList
不是线程安全集合。使用ArrayBlockingQueue
.类arrayblockingqueue