多个线程访问一个ArrayList [英] multiple threads accessing an ArrayList

查看:132
本文介绍了多个线程访问一个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)

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆