2017-05-30 49 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(); 
} 
}