在Java中使用轮询是不是很糟糕?

Art*_*ans 32 java multithreading

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

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

 // do stuff with one element of the array
 // remove element from array
 // and call the loop again
Run Code Online (Sandbox Code Playgroud)

我在嵌入式系统编程中做过类似的事情,但在Java中使用它是否安全?关注的是通过在非常快的时间内循环迭代来解决过程功耗问题.

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

问题是 - 我是否需要添加睡眠或我不应该关注这个?

有关更安全/更好的系统的任何建议,以检查数组中的新数据?

ass*_*ias 53

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

像你描述的那样忙着等待不必要地消耗cpu资源.

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

  • +1由于长度不是易失性的,JIT很可能将读取值缓存在寄存器中,因此我预计它在预热后看不到变化. (4认同)
  • @Arturs如果你的arraylist变量是volatile(让我们称之为`volatile myList = someArrayList;`),你可以保证如果你给它写一个新值:`myList = someOtherArrayList;`,那个新值将被其他人看到线程.但就是这样.如果该变量继续引用相同的arraylist并修改该arraylist(通过添加/删除),则无法保证其他线程将看到更改,或者他们将看到`size()`已更改. (4认同)

Tud*_*dor 11

除非您需要等待的时间非常短,因此上下文切换太昂贵,我不会使用旋转.它绝对没有充分的理由浪费CPU周期.

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

对于更高级的构造,生成器 - 消费者模式有专门的数据结构,比如BlockingQueue(选择实现):

一个队列,它还支持在检索元素时等待队列变为非空的操作,并在存储元素时等待队列中的空间可用.