2

我正在使用 Jetty HTTP Client 异步进行大约 50 个 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 的单线程解决方案。

4

1 回答 1

2

使用java.util.concurrent.CountDownLatch来管理它。

来自Eclipse Jetty 8.1.10.v20130312 的 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()以下方法中的调用

请注意,所有示例都使用 aAtomicBoolean 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.
}
于 2013-05-01T22:49:37.450 回答