2013-05-01 217 views
1

我使用Jetty HTTP客户端异步发出约50个HTTP调用。代码看起来像这样:在java中等待异步http请求

List<Address> addresses = getAddresses(); 
final List<String> done = Collections.synchronizedList(new LinkedList<String>()); 
List<ContentExchange> requests; 
for (Address address : addresses) { 
    ContentExchange ce = new ContentExchange() { 
     @Override 
     protected void onResponseComplete() throws IOException { 
      //handle response 
      done.add("done"); 
     } 
    } 
    ce.setURL(createURL(address)); 
    requests.add(ce); 
} 
for (ContentExchange ce : requests) { 
    httpClient.send(ce); 
} 

while (done.size() != addresses.size()) { 
    Thread.yield(); 
} 

System.out.println("All addresses processed"); 

它调用一个休息服务,返回一些关于地址的数据。我期望它做的是这样的:

  1. 使50个异步(非阻塞)http调用。
  2. 该线程将等待所有50个完成。

但是,它不工作。如果我没有while循环,它工作正常,但我需要等到所有50个完成。有什么方法可以等到全部50完成?

另外我知道有关ExecutorService和多线程解决方案,但我需要一个单线程解决方案与非阻塞IO。

回答

2

使用java.util.concurrent.CountDownLatch来管理这个。

实施例从Eclipse Jetty 8.1.10.v20130312's Siege.java测试类:

final CountDownLatch latch = new CountDownLatch(concurrent); 

for (int i=0;i<concurrent;i++) 
{ 
    ConcurrentExchange ex = new ConcurrentExchange(client,latch,uris,repeats); 
    if (!ex.next()) // this executes the client.send() 
    { 
     latch.countDown(); // count down if client.send() was in error 
    } 
} 

latch.await(); // wait for all ConcurrentExchange's to complete (or error out) 

注:ConcurrentExchange是内Siege.java的私有类。

HttpExchange对象

然后,使用CountDownLatch.countDown()拨打以下方法

请注意,所有示例都使用AtomicBoolean counted来确保它们只计算一次。

if (!counted.getAndSet(true)) // get the value, then set it to true 
{ 
    // only get here if counted returned false. (and that will only happen once) 
    latch.countDown(); // count down this exchange as being done. 
} 
+0

谢谢,使用CountDownLatch工作 – cpprototypes 2013-05-03 00:37:24