BlockingQueue跳过/丢失元素

时间:2017-12-07 22:43:07

标签: multithreading producer-consumer blockingqueue

上下文

据我所知,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()可以得到相同的结果。

简而言之,它更像是单元素变量,而不是队列。我不明白为什么它只是存储所有添加的元素,以便处理线程可以一个接一个地读取它们?

问题:

我做错了什么或是出于这种行为?

虽然现在我考虑过它,但如果单独使用日志记录使得处理程序无法跟上队列增长,我该如何实现来自多个用户的处理数据包呢?我是否必须为每个数据包创建不同的线程?这似乎并不合理。

0 个答案:

没有答案