Java异步HTTP请求

需要用到的包(包版本应该可能不同):

httpcore-4.1.4.jar

httpsayncclient-4.0-alpha3.jar

httpcore-nio-4.2-alpha3.jar

代码(来自http://hc.apache.org/httpcomponents-asyncclient-dev/httpasyncclient/examples/org/apache/http/examples/nio/client/AsyncClientHttpExchangeStreaming.java):

 

[java]   view plain copy
  1. /* 
  2.  * ==================================================================== 
  3.  * Licensed to the Apache Software Foundation (ASF) under one 
  4.  * or more contributor license agreements.  See the NOTICE file 
  5.  * distributed with this work for additional information 
  6.  * regarding copyright ownership.  The ASF licenses this file! 
  7.  * to you under the Apache License, Version 2.0 (the 
  8.  * "License"); you may not use this file except in compliance 
  9.  * with the License.  You may obtain a copy of the License at 
  10.  * 
  11.  *   http://www.apache.org/licenses/LICENSE-2.0 
  12.  * 
  13.  * Unless required by applicable law or agreed to in writing, 
  14.  * software distributed under the License is distributed on an 
  15.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 
  16.  * KIND, either express or implied.  See the License for the 
  17.  * specific language governing permissions and limitations 
  18.  * under the License. 
  19.  * ==================================================================== 
  20.  * 
  21.  * This software consists of voluntary contributions made by many 
  22.  * individuals on behalf of the Apache Software Foundation.  For more 
  23.  * information on the Apache Software Foundation, please see 
  24.  * . 
  25.  * 
  26.  */  
  27. package sync_http;  
  28.   
  29. import java.io.IOException;  
  30. import java.nio.CharBuffer;  
  31. import java.util.concurrent.Future;  
  32.   
  33. import org.apache.http.HttpResponse;  
  34. import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;  
  35. import org.apache.http.nio.IOControl;  
  36. import org.apache.http.nio.client.HttpAsyncClient;  
  37. import org.apache.http.nio.client.methods.AsyncCharConsumer;  
  38. import org.apache.http.nio.client.methods.HttpAsyncMethods;  
  39. import org.apache.http.protocol.HttpContext;  
  40.   
  41. public class AsyncClientHttpExchangeStreaming {  
  42.   
  43.     public static void main(String[] args) throws Exception {  
  44.         HttpAsyncClient httpclient = new DefaultHttpAsyncClient();  
  45.         httpclient.start();  
  46.         try {  
  47.             Future future = httpclient.execute(  
  48.                     HttpAsyncMethods.createGet("http://www.baidu.com/"),  
  49.                     new MyResponseConsumer(), null);  
  50.             Boolean result = future.get();  
  51.             if (result != null && result.booleanValue()) {  
  52.                 System.out.println("Request successfully executed");  
  53.             } else {  
  54.                 System.out.println("Request failed");  
  55.             }  
  56.             System.out.println("Shutting down");  
  57.         } finally {  
  58.             httpclient.shutdown();  
  59.         }  
  60.         System.out.println("Done");  
  61.     }  
  62.   
  63.     static class MyResponseConsumer extends AsyncCharConsumer {  
  64.           
  65.         private int times = 0;  
  66.           
  67.         private String getTimes() {  
  68.             return "\n\n### 第" + ++times + "步\n###";  
  69.         }  
  70.   
  71.         @Override  
  72.         protected void onResponseReceived(final HttpResponse response) {  
  73.             System.out.println(getTimes() + "onResponseReceived");  
  74.         }  
  75.   
  76.         @Override  
  77.         protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {  
  78.             System.out.println(getTimes() + "onCharReceived");  
  79.             while (buf.hasRemaining()) {  
  80.                 System.out.print(buf.get());  
  81.             }  
  82.         }  
  83.   
  84.         @Override  
  85.         protected void releaseResources() {  
  86.             System.out.println(getTimes() + "releaseResources");  
  87.         }  
  88.   
  89.         @Override  
  90.         protected Boolean buildResult(final HttpContext context) {  
  91.             System.out.println(getTimes() + "buildResult");  
  92.             return Boolean.TRUE;  
  93.         }  
  94.   
  95.     }  
  96.   
  97. }  


更多官方例子,参看:http://hc.apache.org/httpcomponents-asyncclient-dev/examples.html

 

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 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() {
     //无论完成还是失败都调用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");
 }
}

你可能感兴趣的:(java)