繁体   English   中英

队列不为空时,BlockingQueue使用者没有响应

[英]BlockingQueue consumer has no response while queue is not empty

我有一个分布式系统,其节点通过套接字接收消息对象。 当在另一个线程中接收和处理消息时,消息将写入BlockingQueue。 我确保机器中只有一个BlockingQueue实例。 传入速率非常高,大约每秒几千。 消费者最初运作良好,但在一段时间后阻止(根本没有响应) - 我已经检查过BlockingQueue不为空,所以不应该被BlockingQueue.take()阻止。 当我手动降低传入消息对象的速率时,消费者的工作非常好。 这很令人困惑......

你能帮我辨认一下这个问题吗? 非常感谢提前。

消费者代码:

ThreadFactory threadFactory = new ThreadFactoryBuilder()
            .setNameFormat(id+"-machine-worker")
            .setDaemon(false)
            .setPriority(Thread.MAX_PRIORITY)
            .build();
ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
executor.submit(new Worker(machine));

public static class Worker implements Runnable {
    Machine machine;
    public Worker(Machine machine) {
        this.machine = machine;
    }
    @Override
    public void run() {
        while (true) {
            try {
                Message message = machine.queue.take();
                // Do my staff here...
            } catch (Exception e) {
                logger.error(e);
            }
        }
    }
}

制片人代码:

// Below code submits the SocketListener runnable described below
ExecutorService worker;
Runnable runnable = socketHandlerFactory.getSocketHandlingRunnable(socket, queue);
worker.submit(runnable);

public SocketListener(Socket mySocket, Machine machine, LinkedBlockingQueue<Message> queue) {
    this.id = machine.id;
    this.socket = mySocket;
    this.machine = machine;
    this.queue = queue;

    try {
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream(), 8192*64);
        ois = new ObjectInputStream(bis);
    } catch (Exception e) {
        logger.error("Error in create SocketListener", e);
    }
}

@Override
public void run() {
    Message message;
    try {
        boolean socketConnectionIsAlive = true;
        while (socketConnectionIsAlive) {
            if (ois != null) {
                message = (Message) ois.readObject();
                queue.put(message);
            }
        }
    } catch (Exception e) {
        logger.warn(e);
    }
}

如果您使用的是无限制队列,可能会因为内存压力而导致整个系统陷入困境。 而且,这意味着产生强度不受消耗强度的限制。 所以,使用有界队列。

另一个建议:在阻塞条件发生时获取完整的线程堆栈跟踪转储,以找出消费者阻止的确定位置。 你可能会有惊喜。

您有几个候选问题区域:

  1. 您使用的是什么实际的BlockingQueue? 你是否达到了ArrayBlockingQueue的上限?

  2. 您为流程分配了多少内存? 即,这个过程的最大堆是多少? 如果从传入消息的重载中达到该堆空间的上限,则完全有可能出现OutOfMemoryError。

  3. 在您的邮件处理过程中实际发生了什么(“我的员工在这里......” [原文如此] )? 是否有可能在该代码中出现死锁,只有在每秒发送许多消息时才会出现这种情况。 你是否在某个调用堆栈中有一个Exception eater,它隐藏了你遇到的真正问题?

  4. 您的记录器在哪里登录? 您是否丢弃了指示性消息,因为它没有记录到您期望的位置?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM