使用LinkedBlockingQueue处理重复的Java Producer / Consumer?

时间:2016-12-16 16:45:33

标签: java queue blockingqueue

我有一个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.");
        }            
    }

}

1 个答案:

答案 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);
  ...