多个线程访问一个ArrayList [英] multiple threads accessing an ArrayList
问题描述
我有是用来缓冲数据,以便其他线程可以阅读它们一个ArrayList
i have an ArrayList that's used to buffer data so that other threads can read them
此阵不断增加它的数据,因为它是从UDP源读取,而其它线程读取不断从array.Then数据从数组中删除。
this array constantly has data added to it since it's reading from a udp source, and the other threads constantly reading from that array.Then the data is removed from the array.
这是不实际的code,但一个简单的例子:
this is not the actual code but a simplified example :
public class PacketReader implements Runnable{
pubic static ArrayList<Packet> buffer = new ArrayList() ;
@Override
public void run(){
while(bActive){
//read from udp source and add data to the array
}
}
public class Player implements Runnable(){
@Override
public void run(){
//read packet from buffer
//decode packets
// now for the problem :
PacketReader.buffer.remove(the packet that's been read);
}
}
在remove()方法从数组中删除数据包,然后转移到右向左覆盖的空白。
The remove() method removes packets from the array and then shifts all the packets on the right to the left to cover the void.
我关心的是:因为缓冲区连续被多个线程添加和读取,将在remove()方法使问题自会得包转移到左侧?
My concern is : since the buffer is constantly being added to and read from by multiple threads , would the remove() method make issues since its gonna have to shift packets to the left?
我是说如果。新增()或获得()方法被调用上的ArrayList,同时这种转变正在做这将是一个问题吗?
i mean if .add() or .get() methods get called on that arraylist at the same time that shift is being done would it be a problem ?
我得到索引超出有时越界异常及其类似的:
指数:100大小300,这是奇怪的Cuz指数尺寸范围内,所以我想知道如果这是有可能引起问题或者我应该寻找其他的问题。
i do get index out of bounds exception sometimes and its something like : index : 100 size 300 , which is strange cuz index is within size , so i want to know if this is what may possibly be causing the problem or should i look for other problems .
感谢您
推荐答案
这听起来像你真正想要的是一个的 的BlockingQueue
。 ArrayBlockingQueue
可能是一个不错的选择。如果你需要一个无界队列,并不在乎额外的内存利用率(相对于 ArrayBlockingQueue
)的 的LinkedBlockingQueue
也适用。
It sounds like what you really want is a BlockingQueue
. ArrayBlockingQueue
is probably a good choice. If you need an unbounded queue and don't care about extra memory utilization (relative to ArrayBlockingQueue
), LinkedBlockingQueue
also works.
它可以让你在推项目和弹出出来,在一个线程安全的,有效的方式。这些push和pop的行为会有所不同(当您尝试推到一个完整的队列,或弹出从空单会发生什么?),以及Javadoc文档的BlockingQueue
接口有一个表,显示所有这些行为的很好。
It lets you push items in and pop them out, in a thread-safe and efficient way. The behavior of those pushes and pops can differ (what happens when you try to push to a full queue, or pop from an empty one?), and the JavaDocs for the BlockingQueue
interface have a table that shows all of these behaviors nicely.
一个线程安全的列表
(不管它是来自 synchronizedList
或的CopyOnWriteArrayList
)实际上不是不够的,因为你的使用情况采用了经典的检查当时的行为模式,这就是天生活泼。考虑这个片断:
A thread-safe List
(regardless of whether it comes from synchronizedList
or CopyOnWriteArrayList
) isn't actually enough, because your use case uses a classic check-then-act pattern, and that's inherently racy. Consider this snippet:
if(!list.isEmpty()) {
Packet p = list.remove(0); // remove the first item
process(p);
}
即使列表
是线程安全的,这种用法是不是!如果列表
在如果检查,但随后另一个线程你到之前将其删除(0)$ c的一个元素$ C>?
Even if list
is thread-safe, this usage is not! What if list
has one element during the "if" check, but then another thread removes it before you get to remove(0)
?
您的可以的解决这个问题了大约两个动作同步:
You can get around this by synchronizing around both actions:
Pattern p;
synchronized (list) {
if (list.isEmpty()) {
p = null;
} else {
p = list.remove(0);
}
}
if (p != null) {
process(p); // we don't want to call process(..) while still synchronized!
}
这是效率较低,需要更多的code比的BlockingQueue
,虽然如此,没有理由这样做。
This is less efficient and takes more code than a BlockingQueue
, though, so there's no reason to do it.
这篇关于多个线程访问一个ArrayList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!