亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Vertx HTTPClient 與 CompletableFuture 阻塞回調線程

Vertx HTTPClient 與 CompletableFuture 阻塞回調線程

慕田峪7331174 2021-10-28 15:51:00
我正面臨一個非常奇怪的問題。我正在使用 Vert.x 和處理程序,我正在使用 Vert.x 調用 REST API HttpClientRequest?,F在我有一個CompletableFuture我正在HttpClientRequest. 后來,我使用CompletableFuture.get(). 但是無論何時get()調用方法,主線程都會被阻塞(正如預期的那樣),但它會永遠被阻塞。我沒有看到回調發生在我的響應處理程序上并且它永遠被卡住了。這是代碼:import io.vertx.core.http.HttpClientRequest;import io.vertx.core.http.HttpMethod;import io.vertx.core.json.Json;import io.vertx.core.json.JsonObject;import java.util.concurrent.CompletableFuture;import io.vertx.core.http.HttpClient;CompletableFuture<JsonObject> comp = new CompletableFuture<JsonObject>();   HttpClient httpClient = new HttpClient(); //This object initialized and set the endpoit, port and domain name.HttpClientRequest request = httpClient.request(HttpMethod.POST, requestURI, response -> {        response.bodyHandler(body -> {            //do some process            comp.complete(new JsonObject(body);        });    }).exceptionHandler(e -> {        //log the error        comp.completeExceptionally(e);    });request.end();//after some processcomp.get();  // here main thread is stuck forever.我的 API 給出了 200 個響應,我在 Wireshark 中看到了,如果我執行comp.thenAccept()回調,它會給出我的結果。為什么會發生這種情況,解決方案是什么?
查看完整描述

2 回答

?
湖上湖

TA貢獻2003條經驗 獲得超2個贊

您的實現的問題在于它違反了黃金法則 - 不要阻止事件循環。您不應該像CompletableFuture.get()在事件循環中那樣調用阻塞操作。同樣,sampleHandler()也不應該調用Thread.sleep()事件循環,但這是一個較小的問題。


結果是你的事件循環現在被阻塞了……所以你的/sample請求不能再被處理了。并且由于請求沒有被處理,你CompletableFuture仍然沒有完成……死鎖。


這個問題有兩種可能的解決方案:


CompletableFuture按設計使用,依賴于鏈式調用而不是get(),盡管它不強制執行 Vert.x 的線程模型。例如:


comp.whenComplete((result, e) -> {

    System.out.println("Got sample response");

    if (e != null) {

        context.response().setStatusCode(500)

                .end(e.getMessage());

    } else {

        context.response().setStatusCode(200)

                .putHeader("content-type", "text/html")

                .end(result);

    }

    System.out.println("end testCompBlocking....");

});

使用 Vert.x 工具運行阻塞代碼。這應該不是必需的,CompletableFuture但其他 API 可能需要它。例如:


context.vertx().<String>executeBlocking(future -> {

            String result = "Not Success";

            try {

                result = comp.get();

            } catch (Exception e) {

                System.out.println("Exception in getting from Completable..." + e.getMessage());

                e.printStackTrace();

            }

            future.complete(result);

        },

        false,

        result -> {

            context.response().setStatusCode(200);

            context.response().putHeader("content-type", "text/html");

            context.response().end(result.result());

            System.out.println("end testCompBlocking....");

        });


查看完整回答
反對 回復 2021-10-28
?
拉丁的傳說

TA貢獻1789條經驗 獲得超8個贊

get() 阻塞主線程直到未來完成,但是,HttpClientRequest 在主線程上執行,因此這種情況會導致死鎖。

相反,它thenAccept()是非阻塞的,僅創建一個在未來完成時執行的回調。


根據您提供的代碼,您的用例不清楚;您是否有理由分別使用HttpClientandCompletableFuture而不是WebClientand Future?

如果您需要使用 CompletableFuture,那么您應該查看項目以獲得與 Vert.x 更兼容的實現。


查看完整回答
反對 回復 2021-10-28
  • 2 回答
  • 0 關注
  • 644 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號