我目前正在开发一个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中放入/轮询数据时,它不应该在线程之间正常工作吗?我错过了什么?
感谢您的任何见解。
答案 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(...)
并在将数组添加到队列中以及何时删除它们时将其转储到数组中?我想你会发现队列不是问题。