• Java利用httpasyncclient进行异步HTTP请求


    Java利用httpasyncclient进行异步HTTP请求

    前段时间有个需求在springmvc mapping的url跳转前完成一个统计的业务。显然需要进行异步的处理,不然出错或者异常会影响到后面的网页跳转。异步的方式也就是非阻塞式的,当异步调用成功与否程序会接着往下执行,不必等到输入输出处理完毕才返回。

    主要用到httpasyncclient-4.0.1.jar,httpclient-4.3.2.jar,httpcore-4.3.2.jar,httpcore-nio-4.3.2.jar,commons-logging-1.1.3.jar。

    java.util.concurrent中主要包括三类工具,Executor Freamework,并发集合(Concurrent Collection),以及同步器(Synchronizer)。下面的例子是利用java.util.concurrent.Future只请求一个 url异步请求。Future接口表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

    import java.util.concurrent.Future;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
    import org.apache.http.impl.nio.client.HttpAsyncClients;
    /**
     * This example demonstrates a basic asynchronous HTTP request / response
     * exchange. Response content is buffered in memory for simplicity.
     */
    public class AsyncClientHttpExchange {
     public static void main(final String[] args) throws Exception {
      CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();// 默认的配置
      try {
       httpclient.start();
       HttpGet request = new HttpGet("http://www.apache.org/");
       Future<HttpResponse> future = httpclient.execute(request, null);
       HttpResponse response = future.get();// 获取结果
       System.out.println("Response: " + response.getStatusLine());
       System.out.println("Shutting down");
      } finally {
       httpclient.close();
      }
      System.out.println("Done");
     }
    }

    同步器(Synchronizer)是一些使线程能够等待另一个线程的对象,允许它们协作,最常用的同步器是CountDownLatch和 Semaphore。较不常用的是CyclicBarrier和Exchanger。Semaphore类是一个计数信号量。从概念上讲,信号量维护了一 个许可集。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。 CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,可使用 CyclicBarrier。倒计数索存器(CountDownLatch)是一次性的障碍。它的唯一构造器带有一个int类型的参数,这个参数是指允许 所有的等待线程处理之前,必须在锁存器上调用countDown()方法的次数。这一点非常有用。下面是异步请求一组url的例子,利用callback 借口完成独立的操作。

     
    import java.util.concurrent.CountDownLatch;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.concurrent.FutureCallback;
    import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
    import org.apache.http.impl.nio.client.HttpAsyncClients;
    /**
     * This example demonstrates a fully asynchronous execution of multiple HTTP
     * exchanges where the result of an individual operation is reported using a
     * callback interface.
     */
    public class AsyncClientHttpExchangeFutureCallback {
     public static void main(final String[] args) throws Exception {
      RequestConfig requestConfig = RequestConfig.custom()
        .setSocketTimeout(3000).setConnectTimeout(3000).build();
      CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
        .setDefaultRequestConfig(requestConfig).build();
      try {
       httpclient.start();
       final HttpGet[] requests = new HttpGet[] {
         new HttpGet("http://www.apache.org/"),
         new HttpGet("https://www.verisign.com/"),
         new HttpGet("http://www.google.com/"),
         new HttpGet("http://www.baidu.com/") };
       final CountDownLatch latch = new CountDownLatch(requests.length);
       for (final HttpGet request : requests) {
        httpclient.execute(request, new FutureCallback<HttpResponse>() {
         //无论完成还是失败都调用countDown()
         @Override
         public void completed(final HttpResponse response) {
          latch.countDown();
          System.out.println(request.getRequestLine() + "->"
            + response.getStatusLine());
         }
         @Override
         public void failed(final Exception ex) {
          latch.countDown();
          System.out.println(request.getRequestLine() + "->" + ex);
         }
         @Override
         public void cancelled() {
          latch.countDown();
          System.out.println(request.getRequestLine()
            + " cancelled");
         }
        });
       }
       latch.await();
       System.out.println("Shutting down");
      } finally {
       httpclient.close();
      }
      System.out.println("Done");
     }
    }

    参考文档:http://hc.apache.org/httpcomponents-asyncclient-dev/examples.html

  • 相关阅读:
    MySQL配置文件
    Linux安装MySQL以及版本说明
    RabbitMQ之Routing(路由有选择的接收)
    RabbitMQ之Publish/Subscribe(发布/订阅)
    RabibitMQ之Work Queues
    RabbitMQ简单生产者消费者(一对一)发送消息
    Linux下安装RabbitMQ
    PyQt5+qtdesigner开发环境配置
    利用sql语句建立全国省市区三级数据库
    完整项目:网上图书商城(一、MySQL数据库设计)未完
  • 原文地址:https://www.cnblogs.com/timssd/p/5068185.html
Copyright © 2020-2023  润新知