我有一个linkedblockingqueue,我在处理列表时看到重复的消息。任何人都知道如何使用这种方法产生重复?下面是队列的声明,然后是每个生产者和消费者的run()函数。
当我在一个帖子中执行此操作时,我不会重复。意思是我不使用队列只读取UDP输入并直接在单个线程中调用ProcessScadaMsg newMessage = new ProcessScadaMsg(byte [])。这导致了问题,因为UDP消息进入太快并且错过了所以我不得不将它们分成生产者/消费者。
//Declaration
public static BlockingQueue<byte[]> UDPMessageQueue = new LinkedBlockingQueue<byte[]>();
// Producer
public void run()
{
DatagramSocket receiveSock = null;
// Create socket for receiving data
try
{
receiveSock = new DatagramSocket(port);
} catch (SocketException e2)
{
// TODO Auto-generated catch block
errorLog.error("Unable to open socket.");
}
while (true)
{
// buffer to receive incoming data
byte[] buffer = new byte[DataAdapterFB1.HEADER_SIZE + DataAdapterFB1.MAX_DATA_BYTES];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
try
{
receiveSock.receive(incoming);
} catch (IOException e1)
{
errorLog.fatal("Failed to read from IO port.");
System.exit(1);
} catch (NullPointerException e2)
{
errorLog.fatal("IO Port unavailable or in use.");
System.exit(1);
}
DataAdapterFB1.UDPMessageQueue.add(incoming.getData());
}
// Consumer
public void run()
{
while (true)
{
try
{
ProcessScadaMsg newMessage = new ProcessScadaMsg(DataAdapterFB1.UDPMessageQueue.take());
} catch (InterruptedException e)
{
errorLog.warn("Queue processing interrupted.");
}
}
}
答案 0 :(得分:1)
您正在创建一个包含缓冲区的DatagramPacket对象,然后您在该数据包的循环中多次接收。所以,假设您背靠背收到两个数据包。当收到第一个缓冲区时,缓冲区将被填充,并作为第一个节点添加到列表中。当接收到第二个数据包时,它被写入存储器中的相同缓冲区,并且这种缓冲区在第二个节点中排队。
因此,从消费者的角度来看,当第一个节点出列时,它将指向与第二个节点相同的缓冲区,其内容已被第二个节点覆盖。
您需要在循环中分配缓冲区和DatagramPacket:
while (true)
{
// buffer to receive incoming data
byte[] buffer = new byte[DataAdapterFB1.HEADER_SIZE + DataAdapterFB1.MAX_DATA_BYTES];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
...