我需要在我的代码中处理以下情况:
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结束时返回结果?
答案 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();
}
}