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

Java 当队列不为空时,BlockingQueue使用者没有响应,java,producer-consumer,blockingqueue,Java,Producer Consumer,Blockingqueue,我有一个分布式系统,其节点通过套接字接收消息对象。在另一个线程中接收和处理消息时,会将消息写入BlockingQueue。我确保一台机器中只有一个BlockingQueue实例。的传入速率非常高,大约每秒数千次。消费者一开始工作得很好,但是在一段时间后阻塞(根本没有响应)-我已经检查过BlockingQueue不是空的,所以不应该被BlockingQueue.take()阻塞。当我手动降低传入消息对象的速率时,消费者工作得非常好。这是相当令人困惑的 你能帮我找出这个问题吗?先谢谢你 消费者代码:

我有一个分布式系统,其节点通过套接字接收消息对象。在另一个线程中接收和处理消息时,会将消息写入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);
    }
}
//下面的代码提交下面描述的可运行的SocketListener
服务人员;
Runnable Runnable=socketHandlerFactory.getSocketHandlingRunnable(套接字,队列);
worker.submit(可运行);
公共SocketListener(Socket mySocket、机器、LinkedBlockingQueue队列){
this.id=machine.id;
this.socket=mySocket;
这个机器=机器;
this.queue=队列;
试一试{
BufferedInputStream bis=新的BufferedInputStream(socket.getInputStream(),8192*64);
ois=新的ObjectInputStream(bis);
}捕获(例外e){
logger.error(“创建SocketListener时出错”,e);
}
}
@凌驾
公开募捐{
信息;
试一试{
布尔SocketConnectionsAlive=true;
while(socketconnectionsalive){
如果(ois!=null){
message=(message)ois.readObject();
queue.put(消息);
}
}
}捕获(例外e){
记录器警告(e);
}
}

如果您使用的是无界队列,则可能会发生由于内存压力导致整个系统陷入困境的情况。此外,这意味着生产强度不受消费强度的限制。因此,使用有界队列


另一个建议是:当阻塞条件发生时,获取完整的线程stacktrace转储,以确定使用者阻塞的位置。您可能会在那里得到惊喜。

您有几个候选问题领域:

  • 您实际使用的阻塞队列是什么?您是否达到了ArrayBlockingQueue的上限

  • 您为进程分配了多少内存?也就是说,这个过程的最大堆是多少?如果由于传入消息的过载而达到堆空间的上限,则完全有可能出现OutOfMemoryError

  • 在您的消息处理过程中实际发生了什么(“我的员工在这里……[sic])?是否有可能在代码中存在死锁,只有在每秒发送多条消息时才会公开该死锁。在调用堆栈的某个地方是否有一个异常食客隐藏了您遇到的真正问题

  • 你的伐木工人在哪里登录?您是否因为没有登录到您期望的位置而丢弃指示消息


  • 线程转储显示了什么?谢谢Marko,你的宝贵建议解决了我的确切问题@马克托波尼克只是好奇;即使是有界阻塞队列;我的所有线程仍然被阻止,无法将数据添加到队列中,对吗?如何解决这些问题。@KanagaveluSugumar阻塞是好的,这意味着如果生产方超过消费者太多,生产方就会受到反压力。让生产商永远不阻塞的唯一方法是确保消费者能够处理生产商提供的所有负载。感谢Bob提供的详细检查点-所有这些都有助于我仔细反思我的情况。