[英]Syncing multiple asynchronous requests in Java
我使用Java中的官方Telegram Api(TDLib)來請求有關組中所有成員的信息。 使用他們的ID我向服務器發送異步請求,我在ResultHandler中接收每個請求的User
對象,如下所示:
private static ArrayList<TdApi.User> chatUsers= new ArrayList<>();
private static void addUsers(){
for (int i = 0; i < userIDs.length; i++){
client.send(new TdApi.GetUser(userIDs[i]), new Client.ResultHandler() {
@Override
public void onResult(TdApi.Object object) {
TdApi.User user = (TdApi.User)object;
chatUsers.add(user);
}
});
}
}
由於我對Java中的任何同步請求都很陌生,我想知道以下內容:
在繼續之前調用此方法並等待收到的所有結果的適當方法是什么?
通常,在繼續執行下一個請求之前連續調用多個請求並等待每個結果時,通常的方法是什么,而不是將請求嵌套在彼此內部以在Java中同步它們? 我想避免這樣的事情:
private static void getSupergroupId(int chatId){ //first step client.send(new TdApi.GetChat(chatId), new Client.ResultHandler() { @Override public void onResult(TdApi.Object object) { supergroupId = ((TdApi.ChatTypeSupergroup)((TdApi.Chat)object).type).supergroupId; //second step when result received client.send(new TdApi.GetSupergroupMembers(supergroupId, null, 0, 200), new Client.ResultHandler() { @Override public void onResult(TdApi.Object object) { chatMembers = ((TdApi.ChatMembers)object).members; //further steps which need to wait for the result of the step before } }); } }); }
謝謝!
1其中一個Java Synchronizer應該可以工作。 我會從CountDownLatch
開始,因為它是最簡單的一個。
private static final ArrayList<TdApi.User> chatUsers = Collections.synchronizedList(new ArrayList<>());
private static void addUsers() {
final CountDownLatch latch = new CountDownLatch(userIDs.length);
for (int i = 0; i < userIDs.length; i++) {
client.send(new TdApi.GetUser(userIDs[i]), new Client.ResultHandler() {
@Override
public void onResult(TdApi.Object object) {
TdApi.User user = (TdApi.User) object;
chatUsers.add(user);
latch.countDown();
}
});
}
// handle InterruptedException
latch.await(10, TimeUnit.SECONDS);
}
請注意, chatUsers
是從不同的線程訪問的,因此應該通過鎖保護對它的訪問。 為簡單起見,我在示例中使用了Collections.synchronizedList
。 但是,您應該使用更細粒度的方法。
2看看Completablefuture
,看來這就是你要找的東西。
private static void getSupergroupId(int chatId) {
CompletableFuture.supplyAsync(() -> {
AtomicReference<TdApi.ChatTypeSupergroup> atomicReference = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
client.send(new TdApi.GetChat(chatId), new Client.ResultHandler() {
@Override
public void onResult(TdApi.Object object) {
atomicReference.set(((TdApi.ChatTypeSupergroup) ((TdApi.Chat) object).type).supergroupId);
latch.countDown();
}
});
// handle InterruptedException
latch.await(10, TimeUnit.SECONDS);
return atomicReference.get();
}).thenApply(supergroupId -> {
AtomicReference<TdApi.ChatMembers> atomicReference = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
client.send(new TdApi.GetSupergroupMembers(supergroupId, null, 0, 200), new Client.ResultHandler() {
@Override
public void onResult(TdApi.Object object) {
atomicReference.set((TdApi.ChatMembers) object).members;
latch.countDown();
}
});
// handle InterruptedException
latch.await(10, TimeUnit.SECONDS);
return atomicReference.get();
});
//further steps which need to wait for the result of the step before)
}
請注意,使用CountDownLatch
的相同技巧等待結果。 再次,你應該通過鎖來保護回調,因為它被不同的線程訪問。 為了100%清除它不需要因為在CountDownLatch
上搭載,但是我建議使用顯式同步,例如AtomicReference
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.