Java ConcurrentLinkedQueue行为奇怪

时间:2015-04-23 21:42:15

标签: java concurrency queue packets

我正在开展一个项目,在这个项目中,我将某些数据包添加到队列中以便稍后处理(下一个600ms的时间段处理队列中的所有数据包)。

但是,我目前遇到的问题是,当在同一个周期内接收到两个数据包时,队列的表现非常奇怪。

在班上我有

    private ConcurrentLinkedQueue<RSPacket> logicPackets;

public LogicDecoder() {
    super();
    logicPackets = new ConcurrentLinkedQueue<RSPacket>();
    addDecodeable(new SendWalk());
}

并添加我有的数据包

    @Override
public void decode(RSPacket packet, Session session) {
    GameServer.get().logger().debug("LogicDecoder decoded " +  packet.getId() + " - " + packet.getLength() + " - " + packet.getOffset());
    for (RSPacket p : logicPackets) {
        if (p.getId() == packet.getId()) {
            logicPackets.remove(p);
            GameServer.get().logger().debug("Removed packet from queue with id " + packet.getId());
            break;
        }
    }
    logicPackets.add(packet);
    for (RSPacket p : logicPackets) {
        GameServer.get().logger().debug("LogicDecoder containsOnDecode " + p.getId());
    }
}

这是调用decode的代码,这是decodeDecodables()方法的重要部分 注意:当我尝试不使用getConvertedPacket()

时,仍会出现同样的问题
Decoder d = (Decoder) handler;
            P converted = (P) d.getConvertedPacket(packet, session);
            if (packet.getId() != PACKET.PING.getId()) {
                GameServer.get().logger().debug(packet.getId() + " -> " + converted.getId());
            }
            if (d.canHandle(converted, session) && d.preDecode(converted, session)) {
                d.decode(converted, session);
                return true;
            }

最后,以下是最终使用队列的方法:

    @Override
public void onTick(Session session) {
    super.onTick(session);
    //GameServer.get().logger().debug("We have " + logicPackets.size() + " logicPackets to process");
    for (RSPacket p : logicPackets) {
        GameServer.get().logger().debug("pending packet id: " + p.getId());
    }
    RSPacket packet;
    while ((packet = logicPackets.poll()) != null) {
        //GameServer.get().logger().debug("LogicDecoder onTick Poll " + PACKET.forId(packet.getId()).name());
        if (!preDecode(packet, session) || !decodeDecodeables(packet, session)) {
            decodeFail(packet, session);
        }
    }
}

以下是id为8的数据包和id为59的数据包背靠背发送时的输出。

[17:31:32] -> WorldDecoder recieved packet 8
[17:31:32] -> 8 -> 8
[17:31:32] -> LogicDecoder decoded 8 - 21 - 2
[17:31:32] -> LogicDecoder containsOnDecode 8
[17:31:32] -> WorldDecoder recieved packet 59
[17:31:32] -> 59 -> 59
[17:31:32] -> LogicDecoder decoded 59 - 21 - 12
[17:31:32] -> Removed packet from queue with id 59
[17:31:32] -> LogicDecoder containsOnDecode 59

如您所见,第一遍很好,它将数据包8添加到队列中,然后当数据包59再次调用该函数时,它决定我们之前添加的数据包(数据包8)现在是数据包59和在添加之前删除它。老实说,我不知道这里发生了什么。

1 个答案:

答案 0 :(得分:1)

通过更改数据包类来实现Cloneable,我能够解决这个问题:

logicPackets.add(packet);

对此:

 logicPackets.add((RSPacket)packet.clone());