Java ConcurrentLinkedQueue 行为异常
Java ConcurrentLinkedQueue behaving oddly
我正在做一个项目,在这个项目中我将某些数据包添加到队列中以供稍后处理(接下来的 600 毫秒滴答处理队列中的所有数据包)。
但是,我目前遇到的问题是,当在同一周期内接收到两个数据包时,队列的行为非常奇怪。
在我的 class 顶部 我有
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());
}
}
这是调用解码的代码,这是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 并在添加自身之前将其删除。老实说,我不知道这里发生了什么。
通过更改数据包 class 以实现 Cloneable,我能够修复此修改:
logicPackets.add(packet);
为此:
logicPackets.add((RSPacket)packet.clone());
我正在做一个项目,在这个项目中我将某些数据包添加到队列中以供稍后处理(接下来的 600 毫秒滴答处理队列中的所有数据包)。
但是,我目前遇到的问题是,当在同一周期内接收到两个数据包时,队列的行为非常奇怪。
在我的 class 顶部 我有
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());
}
}
这是调用解码的代码,这是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 并在添加自身之前将其删除。老实说,我不知道这里发生了什么。
通过更改数据包 class 以实现 Cloneable,我能够修复此修改:
logicPackets.add(packet);
为此:
logicPackets.add((RSPacket)packet.clone());