Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何停止java方法,直到它收到来自MQTT代理的消息_Java_Mqtt_Paho - Fatal编程技术网

如何停止java方法,直到它收到来自MQTT代理的消息

如何停止java方法,直到它收到来自MQTT代理的消息,java,mqtt,paho,Java,Mqtt,Paho,我有一个包含2个方法的类,每个方法分别发布和订阅一个公共MQTT代理 public class operations{ public void fetch(){ // do something mqttConn.mqttSubscriberFetch(MQTTtopic); // do something } public void store(){ // do something mqttConn.mqttSubscribe

我有一个包含2个方法的类,每个方法分别发布和订阅一个公共MQTT代理

public class operations{
    public void fetch(){
    // do something

     mqttConn.mqttSubscriberFetch(MQTTtopic);

    // do something
   }

    public void store(){
   // do something

    mqttConn.mqttSubscriberStore(MQTTtopic);

   // do something
   }

}
方法获取的MQTT方法如下所示:

public class mqttConnectionFetch implements  MqttCallback{

    MqttClient client;

    String topic;

    public mqttConnectionFetch() {
    }


    public void mqttSubscriberFetch(String topic) {

        final String MQTT_BROKER = "tcp://localhost:1883" ;
        final String CLIENT_ID = "fetch";
        try {
            client = new MqttClient(MQTT_BROKER, CLIENT_ID);
            client.connect();
            client.setCallback(this);
            client.subscribe(topic);
            MqttMessage message = new MqttMessage();

        } catch (MqttException e) {
            e.printStackTrace();
        }
    }



    @Override
    public void connectionLost(Throwable cause) {
        // TODO Auto-generated method stub

    }

    @Override
    public void messageArrived(String topic, MqttMessage message)
            throws Exception {

        System.out.println("the message received is "+message);

        if(message.toString().equals("Processed")) {
            MqttPublisherFetch("Processed", "operations/fetch");

        }

    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        // TODO Auto-generated method stub

    }


    public void MqttPublisherFetch(String message, String topic) {
        final String MQTT_BROKER = "tcp://localhost:1883" ;
        final String CLIENT_ID = "store";
        try {
            client = new MqttClient(MQTT_BROKER, CLIENT_ID);
            client.connect();
            createMqttMessage(message,topic);
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private void createMqttMessage(String message, String topic) throws MqttException {
        MqttMessage publishMessage = new MqttMessage();
        publishMessage.setPayload(message.getBytes());
        client.publish(topic, publishMessage);

    }


}
现在,我正试图实现这样一种功能,即每当我的fetch方法订阅一个主题时,如果来自代理的消息处于“处理”状态,它就应该处于等待状态。而存储方法应该正常工作。当收到的消息被“处理”后,提取应该再次开始工作

我用普通的java wait()和start()进行了尝试,但没有得到所需的输出。
有人能帮我解开这个谜团吗?

据我所知,存储方法由几个步骤组成。其中一个步骤是通过MQTT发送消息并等待响应。从
store
方法的客户机的角度来看,它是同步的,即客户机只有在整个处理(包括通过MQTT异步发送/接收)完成后才会接收响应

这里要解决的是一个经典问题,当一个线程需要等待另一个线程中发生某种情况时。有很多方法可以实现这一点,只需检查中提出的选项数量

最简单的方法是使用
倒计时闩锁
。我将使用
fetch
方法,因为这是您提供代码的方法

首先,您需要修改
mqttSubscriberFetch
以创建内部
CountDownLatch
对象:

private CountDownLatch processingFinishedLatch;

public void mqttSubscriberFetch(String topic) {

    final String MQTT_BROKER = "tcp://localhost:1883" ;
    final String CLIENT_ID = "fetch";
    try {
        client = new MqttClient(MQTT_BROKER, CLIENT_ID);
        client.connect();
        client.setCallback(this);
        client.subscribe(topic);
        MqttMessage message = new MqttMessage();
        processingFinishedLatch = new CountDownLatch(1);

    } catch (MqttException e) {
        e.printStackTrace();
    }
}
然后您需要在消息接收回调中触发此信号:

@Override
public void messageArrived(String topic, MqttMessage message)
        throws Exception {

    System.out.println("the message received is "+message);

    if(message.toString().equals("Processed")) {
        MqttPublisherFetch("Processed", "operations/fetch");
        this.processingFinishedLatch.countDown();
    }

}
您还需要为
mqttConnectionFetch
的客户端提供一种等待闩锁变为零的方法:

void waitForProcessingToFinish() throws InterruptedException {
     this.processingFinishedLatch.await();
}
fetch
方法应该这样使用它:

public void fetch(){
// do something

mqttConn.mqttSubscriberFetch(MQTTtopic);

// do everything that is needed to initiate processing

mqttConn.waitForProcessingToFinish()

// do something
}

执行
fetch
的线程将在
waitForProcessingToFinish
中等待,直到闩锁达到零,并在相应的消息出现时发生

这种方法可以很容易地修改,以便在消息从未出现时解决问题。只需使用:

fetch
应该检查返回的值,如果发生超时,可能会将错误返回给调用方

请注意,此解决方案有一个缺点,即正在处理
fetch
的线程将一直处于繁忙状态。如果这是线程池中用于处理传入HTTP请求的线程,则可能会限制服务器可以并发处理的请求数。
有一些方法可以缓解这种情况,例如,或。这个问题的实际解决方案在很大程度上取决于您用于REST API实现的技术。

为什么不简单地使用观察者/监听器模式,并在状态更改通知时调用适当的方法呢?首先,在同一进程中运行多个MQTT客户机几乎没有什么好的理由,一个对发布和订阅都很好我不确定我是否理解你想要什么。。。以书面形式获取客户机订阅MQTT服务器并等待,只有当它从代理接收到消息时才会唤醒。如果它接收到来自代理的“正在处理”消息,它可以忽略/记录它并返回等待(这是它将要做的);如果它收到一条“已处理”的消息,它可以处理它,然后返回等待下一条消息。您希望如何改变这种行为?如果远程客户端关闭,而您从未收到响应,又会发生什么情况?看起来您正在解决一些问题,但正如前面指出的那样,这已经是一种非常低效的方式。你能描述一下你为什么需要这样做吗?基本上你能描述你试图解决的更高层次的问题吗。
boolean waitForProcessingToFinish(long timeout,
        TimeUnit unit) throws InterruptedException {
     return this.processingFinishedLatch.await();
}