2017-05-30 47 views
1

我有以下的情况下,我需要在我的代码来处理:的Java实现来处理回调消息

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()和请求2()通过请求者这类型的IRequester

public interface IRequester { 

    request1(); 

    List request2(); 
} 

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

public NetworkManager implements IRequester { 

    request1() { 

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

    request2() { 

    } 
} 

现在,我的问题是,当我实现request1()在这里有我需要创建将消息发送到该节点的过程。此过程可以附带回调。节点响应时返回结果。我如何实现这个功能,以便在我的请求1结束时返回结果?

+1

你不能,因为你不知道它需要多长时间到节点得到的信息为你准备好,你需要他们之间的一个回调 –

回答

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更稳定的代码,因为它现在不得不处理与超时和丢失的结果的问题。

0

这里是如何等待使用作为观察员回调和回调的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(); 
} 
0

由于request1(返还型)是无效的,所以你不能从它返回值。 但在实现类IRequester的,你可以通过一个resultObject, 每当request1()方法执行,将结果存储在结果对象,而当你需要得到的结果,你可以从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(); 
} 
}