簡體   English   中英

在Java中同步多個異步請求

[英]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中的任何同步請求都很陌生,我想知道以下內容:

  1. 在繼續之前調用此方法並等待收到的所有結果的適當方法是什么?

  2. 通常,在繼續執行下一個請求之前連續調用多個請求並等待每個結果時,通常的方法是什么,而不是將請求嵌套在彼此內部以在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM