我正在使用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");
它正在调用一个返回一些有关该地址的数据的休息服务。我期望它做的是:
然而,它不起作用。如果我没有while循环,它工作正常,但我需要等到所有50个完成。有没有办法等到所有50个完成?
我也知道ExecutorService和多线程解决方案,但我需要一个带有非阻塞IO的单线程解决方案。
答案 0 :(得分: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.
}