用于处理回调消息的Java实现

时间:2017-05-30 16:44:03

标签: java algorithm design-patterns

我需要在我的代码中处理以下情况:

public class Class1 {

    IRequester requester;

    public Class1(Requester impl) {
        requester = impl;
    }

    public List doSomething() {
        requester.request1();  // sends messages to a set of nodes
        //do some more local processing
        list = requester.request2(); // sends some more messages and returns a list
        return list;
    }
}

在这种情况下,request1()向一组节点发送请求并返回一个结果,该结果将在本地用于更多处理,然后生成request2(),返回一个列表。这需要在doSomething()执行结束时返回。 request1()和request2()是通过IRequester

类型的请求者完成的
public interface IRequester {

    request1();

    List request2();
}

现在,request1()和request2()由实际执行请求的类实现。这是处理节点之间通信的类。

public NetworkManager implements IRequester {

    request1() {

        // Create an operation
        // Add callback to the operation             
        // schedule operation
    }

    request2() {

    }
}

现在,我的问题是当我在那里实现request1()时,我需要创建一个向该节点发送消息的过程。此过程可以附加回调。当节点响应时,它返回结果。我如何实现这一点,以便它在我的request1结束时返回结果?

3 个答案:

答案 0 :(得分:0)

其中一种方法是使用CompletableFuture来跟踪异步值。

public NetworkManager implements IRequester {

    Client client; //some client that works with callbacks

    CompletableFuture<String> request1() {
        CompletableFuture<String> result = new CompletableFuture<>();
        client.request1(someArguments, (calbackResult) -> result.complete(calbackResult));
        return result;
    }
}

此处result是一个承诺,一旦执行回调,它将提供一个值。直到它将是空的。

所以NetworkManager返回CompletableFuture,这意味着结果还没有准备好或者永远不会准备好(如果回调永远不会发生)。

Class1.doSomething尝试从CompletableFuture获取结果时,当前线程将阻塞,直到值可用或发生超时。

这种方法也使Class1.doSomething中的代码更稳定,因为它现在被迫处理超时和缺少结果的问题。

答案 1 :(得分:0)

下面是一个示例,介绍如何使用Observer作为回调等待回调,使用Thread.sleep来模拟长时间运行的异步任务:

public Object request(){
    CompletableFuture<Object> cf = new CompletableFuture<Object>();
    runAsync( (o, arg) -> cf.complete(arg) );
    try { return cf.get(); } 
    catch (Exception e) {throw new RuntimeException(e); }
}

public void runAsync(final Observer o){
    new Thread( () -> {
        try { Thread.sleep(3000L); }
        catch (InterruptedException e) { e.printStackTrace(); }

        String result = "abc";
        o.update(null, result);
    } ).start();
}

答案 2 :(得分:0)

由于request1()的返回类型为void,因此您无法从中返回值。 但是在IRequester的实现类中,你可以传递一个resultObject, 每当request1()方法执行时,它都会将结果存储在结果Object中,当您需要获取结果时,可以从ResultObject获取它

class ResultObject{
getResult(); ///return result
setResult(); ///store result
}


public NetworkManager implements IRequester {

private ResultObject callBackResult;

public ResultObject getResult(){
return callBackResult;
}
public void setResult(ResultObject value){
this.callBackResult=value;
}

request1() {

    // Create an operation
    this.setResult(callProcedure());
    // schedule operation
}

request2() {

}

}

public class Main{  


public static void main(String args){
IRequester r=new NetworkManger();
ResultObject res=new ResultObject();
r.setResult(res);
r.request1();
r.getResult();
r.request2();
}
 }