上下文
据我所知,BlockingQueue用于在线程之间传递数据,即生产者 - 消费者问题。 例如,在我的情况下,我用它来存储收到的DatagramPackets,以便其他线程可以处理它们。目前它只是将所有传入的数据包记录到日志文件中。 这是我用来模仿这个过程的代码:
Cons c = new Cons();
new Thread(c).start();
int i = 0;
byte[] databuf = new byte[1024];
DatagramPacket packet = new DatagramPacket(databuf, databuf.length);
try (DatagramSocket socket = new DatagramSocket(5555)){
while (10 < System.currentTimeMillis()) {
socket.receive(packet);
c.add(packet);
socket.send(new DatagramPacket("OK".getBytes(), "OK".getBytes().length, packet.getAddress(),
packet.getPort()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Cons类处理写入BlockingQueue并将其记录在不同的线程中:
private static class Cons implements Runnable {
LinkedBlockingQueue<DatagramPacket> q = new LinkedBlockingQueue<>();
@Override
public void run() {
while (10 < System.currentTimeMillis()) {
try {
DatagramPacket packet = q.take();
logger.log(Level.INFO, "!" +"Message:" + new String(packet.getData(), packet.getOffset(),
packet.getLength()));
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void add(DatagramPacket p) throws InterruptedException {
q.put(p);
}
客户端只发送此服务器收到的设定数量的数据包。
问题:
如果从队列读取的线程以某种方式延迟,则它开始跳过元素。在上面的代码示例中,它模仿了Thread.sleep(),但即使单独记录也足以使它偶尔跳过几个元素。线程在队列中请求下一个元素所需的时间越长,它就会跳过更多的元素。使用drainTo()可以得到相同的结果。
简而言之,它更像是单元素变量,而不是队列。我不明白为什么它只是存储所有添加的元素,以便处理线程可以一个接一个地读取它们?
问题:
我做错了什么或是出于这种行为?
虽然现在我考虑过它,但如果单独使用日志记录使得处理程序无法跟上队列增长,我该如何实现来自多个用户的处理数据包呢?我是否必须为每个数据包创建不同的线程?这似乎并不合理。