日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java http异步调用_HttpClient的异步调用,你造吗?

發布時間:2024/3/24 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java http异步调用_HttpClient的异步调用,你造吗? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、前言

HttpClient提供了兩種I/O模型:經典的java阻塞I/O模型和基于Java NIO的異步非阻塞事件驅動I/O模型。

Java中的阻塞I/O是一種高效、便捷的I/O模型,非常適合并發連接數量相對適中的高性能應用程序。只要并發連接的數量在1000個以下并且連接大多忙于傳輸數據,阻塞I/O模型就可以提供最佳的數據吞吐量性能。然而,對于連接大部分時間保持空閑的應用程序,上下文切換的開銷可能會變得很大,這時非阻塞I/O模型可能會提供更好的替代方案。

異步I/O模型可能更適合于比較看重資源高效利用、系統可伸縮性、以及可以同時支持更多HTTP連接的場景。

二、HttpClient中的Future

在HttpClient官網Tutorial的高級話題中,我們可以發現其提供了用于異步執行的FutureRequestExecutionService服務類。

使用FutureRequestExecutionService,允許我們發起http調用后,調用函數馬上返回(調用線程不會阻塞等到相應結果返回)一個Future對象,然后調用線程可以在需要響應結果的地方調用Future對象的get方法來阻塞等待結果。

使用FutureRequestExecutionService的優點是,我們可以使用多個線程并發調度請求、設置任務超時,或者在不再需要響應時取消它們。

FutureRequestExecutionService其實是用一個HttpRequestFutureTask包裝請求,該HttpRequestFutureTask擴展了JDK中的FutureTask。這個類允許我們取消任務、跟蹤各種執行指標,如請求持續時間等。

下面我們看一個例子:

// 1.創建線程池

private static ExecutorService executorService = Executors.newFixedThreadPool(5);

// 2.創建http回調函數

private static final class OkidokiHandler implements ResponseHandler

public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {

// 2.1處理響應結果

return EntityUtils.toString(response.getEntity());

}

}

public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {

// 3.創建httpclient對象

CloseableHttpClient httpclient = HttpClients.createDefault();

// 4.創建FutureRequestExecutionService實例

FutureRequestExecutionService futureRequestExecutionService = new FutureRequestExecutionService(httpclient,

executorService);

// 5.發起調用

try {

// 5.1請求參數

HttpGet httpget1 = new HttpGet("http://127.0.0.1:8080/test1");

HttpGet httpget2 = new HttpGet("http://127.0.0.1:8080/test2");

// 5.2發起請求,不阻塞,馬上返回

HttpRequestFutureTask

HttpClientContext.create(), new OkidokiHandler());

HttpRequestFutureTask

HttpClientContext.create(), new OkidokiHandler());

// 5.3 do somthing

// 5.4阻塞獲取結果

String str1 = task1.get();

String str2 = task2.get();

System.out.println("response:" + str1 + " " + str2);

} finally {

httpclient.close();

}

}

如上代碼1創建了一個線程池用來作為http異步執行的后臺線程,代碼2創建了一個http響應結果處理器,用來異步處理http的響應結果。

代碼3創建了一個HttpClient對象,代碼4創建一個FutureRequestExecutionService,參數1為創建的httpclient對象,參數2為創建的線程池。

代碼5則創建2個Get請求參數,然后執行代碼5.2發起兩個http請求,該調用會馬上返回自己對于的HttpRequestFutureTask對象,調用線程也會馬上返回,然后調用線程就可以在5.3做其他的事情,最后在需要獲取http響應結果的地方,比如代碼5.4調用兩個future的get()方法來獲取結果。

如上基于Future方式,我們可以并發的發起兩個http請求,而之前阻塞方式,則是順序執行的。

但是基于上面Future方式,我們調用線程還是會在代碼5.4阻塞等待響應結果,這并不是我們想要的,我們想要的是事件通知,http確實也提供了注冊CallBack的方式:

首先我們需要實現FutureCallback接口,用來接收通知:

private static final class MyCallback implements FutureCallback

public void failed(final Exception ex) {

System.out.println(ex.getLocalizedMessage());

}

public void completed(final String result) {

System.out.println(result);

}

public void cancelled() {

System.out.println("cancelled");

}

}

然后我們只需要修改代碼5.2,使用三個參數的execute方法發起調用:

// 5.發起調用

try {

// 5.1請求參數

HttpGet httpget1 = new HttpGet("http://127.0.0.1:8080/test1");

HttpGet httpget2 = new HttpGet("http://127.0.0.1:8080/test2");

// 5.2發起請求,不阻塞,馬上返回

HttpRequestFutureTask

HttpClientContext.create(), new OkidokiHandler(), new MyCallback());

HttpRequestFutureTask

HttpClientContext.create(), new OkidokiHandler(), new MyCallback());

//main線程休眠10s,避免請求結束前,關閉了鏈接

Thread.sleep(10000);

...

如上代碼,使用CallBack后,調用線程就得到了徹底解放,就不必再阻塞獲取結果了,當http返回結果后,會自動調用我們注冊的CallBack。

三、HttpAsyncClient-真正的異步

上面HttpClient提供的CallBack的方式,雖然解放了調用線程,但是并不是真正意義上的異步調用,因為其異步調用的支持是基于我們創建的executorService線程。即:雖然發起http調用后,調用線程馬上返回了,但是其內部還是使用executorService中的一個線程阻塞等待響應結果。

HttpAsyncClient則使用Java NIO的異步非阻塞事件驅動I/O模型,實現了真正意義的異步調用,使用HttpAsyncClient我們需要引入其專門的包:

然后改造后代碼如下:

// 1.創建CallBack

private static final class MyCallback implements FutureCallback

public void failed(final Exception ex) {

System.out.println(ex.getLocalizedMessage());

}

public void completed(final HttpResponse response) {

try {

System.out.println(EntityUtils.toString(response.getEntity()));

} catch (ParseException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public void cancelled() {

System.out.println("cancelled");

}

}

public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {

// 2.創建異步httpclient對象

CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().build();

// 3.發起調用

try {

// 3.0啟動

httpclient.start();

// 3.1請求參數

HttpGet httpget1 = new HttpGet("http://127.0.0.1:8080/test1");

HttpGet httpget2 = new HttpGet("http://127.0.0.1:8080/test2");

// 3.2發起請求,不阻塞,馬上返回

httpclient.execute(httpget1, new MyCallback());

httpclient.execute(httpget2, new MyCallback());

// 3.3休眠10s,避免請求執行完成前,關閉了鏈接

Thread.sleep(10000);

} finally {

httpclient.close();

}

}

如上代碼1,創建異步回調實現,用于處理Http響應結果。代碼2創建了異步HttpClient,代碼3.0啟動client,代碼3.2發起請求。

基于Java NIO的異步,當發起請求后,調用方不會使用任何線程同步等待http服務端的響應結果(少量的NIO線程不算哦,因為其個數固定,并且不隨并發請求數量變化),而是會使用少量內存來記錄請求信息,以便服務端響應結果回來后,可以找到對應的回調函數進行執行。

四、總結

本文概要講解了Http的異步調用,關于更多Java中異步調用與異步執行的知識,可以參考《Java異步編程實戰》

更多技術分享,請掃描關注微信公眾號:

file0人點贊博文

總結

以上是生活随笔為你收集整理的java http异步调用_HttpClient的异步调用,你造吗?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。