Java 8 我的channel.basicConsume为什么不等待消息

Java 8 我的channel.basicConsume为什么不等待消息,java-8,rabbitmq,message-queue,Java 8,Rabbitmq,Message Queue,每当我启动以下代码时: ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); String exchangeName = "direct_logs";

每当我启动以下代码时:

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();
    String exchangeName = "direct_logs";
    channel.exchangeDeclare(exchangeName, "direct");
    String queueName = channel.queueDeclare().getQueue();
    channel.queueBind(queueName, exchangeName, "red");
    channel.basicQos(1);

    final Consumer consumer = new DefaultConsumer(channel){
        @Override
        public void handleDelivery(String consumerTag,
                                   Envelope envelope,
                                   AMQP.BasicProperties properties,
                                   byte[] body) throws IOException{
            String message = new String(body, "UTF-8");
            System.out.println(message);
            System.out.println("message received");
        }
    };

    channel.basicConsume(queueName, true, consumer);
它不会像文档中暗示的那样开始一个无休止的循环。相反,它会立即停止。 我能让它使用一段时间的唯一方法是用循环替换
channel.basicConsume
,如下所示:

    DateTime startedAt = new DateTime();
    DateTime stopAt = startedAt.plusSeconds(60);
    long i=0;
    try {
        while (stopAt.compareTo(new DateTime()) > 0) {
            channel.basicConsume(queueName, true, consumer);
            i++;
        }
    }finally {
        System.out.println(new DateTime());
        System.out.println(startedAt);
        System.out.println(stopAt);
        System.out.println(i);
    }
一定有更好的方法来暂时听消息,对吗?我错过了什么?
它立即停止收听。

你确定它正在停止吗?
basicConsume
所做的是注册一个消费者来监听一个特定的队列,这样就不需要在循环中执行它。您只执行一次,只要消息到达,就会调用您传递的
消费者
实例的
handleDelivery
方法

rabbitmq库创建的线程应该防止JVM退出。为了退出程序,您应该实际调用
connection.close()

以下是rabbitmq的完整接收器示例:


它实际上和你的差不多。

我也有同样的问题。原因是我在最后给connection.close打电话。但是,basicConsume()方法不会在当前线程上阻塞,而是在其他线程上阻塞,因此会立即调用它后面的代码,即connection.close()。

如果您确实需要停止执行线程,直到消息被使用,您可以实现简单的循环器模式类:

class Looper {

    private boolean exit = false;

    void loop() {
        while (true) {
            if (exit) {
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    void exit() {
        this.exit = true;
    }
}
A那么,在阅读这样的消息时,您可以应用此循环器:

public String basicConsumeMessage(String queue) {

    final String[] messageBody = new String[1];

    try {
        consChannel.basicConsume(queue, new DefaultConsumer(consChannel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
                byte[] body) {
                deliveryTag = envelope.getDeliveryTag();
                messageBody[0] = new String(body, StandardCharsets.UTF_8);
                looper.exit();
            }
        });
    } catch (IOException e) {
        throw new JiraTransportError(e);
    }
    looper.loop();
    return messageBody[0];
}


请注意looper.loop()和looper.exit()方法是如何使用的。

您是否有任何异常,例如ConnectException:Connection Rejected?