ConcurrentLinkedQueue poll()产生损坏的数据?

时间:2013-10-08 19:50:45

标签: java multithreading concurrency thread-safety

我目前正在开发一个Java项目,它在处理原始数据包时处理它们。 libpcap读入数据,然后将每个数据包放入byte [],然后放入ConcurrentLinkedQueue,线程从中读取并处理数据。

    static ConcurrentLinkedQueue<byte[]> packetQueue = new ConcurrentLinkedQueue<byte[]>();

    public void nextPacket(PcapHeader header, ByteBuffer buffer PcapDumper user) {
        pcapBufferCapacity = buffer.capacity();

        if (pcapBufferCapacity > 54) {
            dumper.dump(header, buffer);
        }

        if (pcapBufferCapacity > 43) {
            byte[] packetBytes = new byte[buffer.remaining()];
            buffer.get(packetBytes);
            packetQueue.add(packetBytes); // Data being added to the queue  
        }
    }

然后我有一个正在运行的线程......

Thread thread = new Thread(new Parser()); // Parser extends Runnable

... poll()是工作队列,然后处理数据。

int parserByteCount;
byte[] packetBytes;

public void run() {
    packetBytes = MyClass.packetQueue.poll();
    parserByteCount = packetBytes.length;
    doStuff();
}

当我运行一个Parser()线程时,一切都按预期工作。但是,如果我运行多个解析器线程......

Thread thread2 = new Thread(new Parser());

...来自MyClass.packetQueue.poll()的数据变得腐败,从静态PCAP文件读取时我的结果不一致。考虑到它与一个Parser()线程完美配合但在多个Parser()线程运行时变得腐败,我认为这与并发性有关。但是,当从ConcurrentLinkedQueue中放入/轮询数据时,它不应该在线程之间正常工作吗?我错过了什么?

感谢您的任何见解。

2 个答案:

答案 0 :(得分:2)

int parserByteCount;
byte[] packetBytes;

您的Parser课程的这些成员变量是?它们是否需要在doStuff()内正确解析?

如果你回答两次,你可能会遇到麻烦。请记住线程共享内存。因此,访问可以同时访问的所有实例或类级变量,必须才能同步。请注意,局部变量不是共享的 - 它们存在于堆栈中,这对于每个线程都是唯一的。一个简单的解决方法是将两个关键变量更改为局部变量,必要时将它们作为方法参数传递。

答案 1 :(得分:0)

  

ConcurrentLinkedQueue poll()产生损坏的数据?

如果这意味着ConcurrentLinkedQueue有错,则极不可能。我怀疑它是如何将数据放入队列或者如何使用它。

byte[] packetBytes = new byte[buffer.remaining()];
buffer.get(packetBytes);
packetQueue.add(packetBytes); // Data being added to the queue  

此代码看起来很好。我担心你重新使用了byte[],但我发现这里没有问题。

packetBytes = MyClass.packetQueue.poll();
parserByteCount = packetBytes.length;
doStuff();

这看起来很好,但poll()可能会返回null您应该检查的内容。您可以考虑切换到LinkedBlockingQueue,它允许更多方法等待队列中的条目。但这不会解决你的问题。

这在doStuff()中留下了一些问题。

  • doStuff()是否更新了一些不是synchronized的常见对象?也许是输出文件或其他一些持久性机制?
  • 您是否应该将packetBytes传递给doStuff()而不是将其作为实例变量?
  • 您处理的任何部分是否会不恰当地修改packetBytes数组?不知道为什么这可以用于一个线程而不是两个线程。
  

来自MyClass.packetQueue.poll()的数据变得腐败,我的结果不一致

你能更清楚地了解“腐败”吗?您是否可以执行System.out.println(...)并在将数组添加到队列中以及何时删除它们时将其转储到数组中?我想你会发现队列不是问题。