【发布时间】:2019-04-09 16:28:37
【问题描述】:
我有一段代码如下所示:
public List<Restaurant> getAllRestaurants() {
List<Restaurant> restaurants = getRestaurants().subList(0, 7); // This takes 234 ms to execute on average.
// There are 7 items in the restaurants list
for (Restaurant restaurant : restaurants) {
PlacesAPIResponse response = callGooglePlacesAPI(restaurant); // A call to the Google API should take 520ms for a given restaurant
restaurant.setRating(response.getRating());
}
return restaurants;
}
如果我如图所示在 for-each 循环中执行上述语句,我预计该方法的总时间为 234ms + (7*520)ms = 3874ms,因为语句是按顺序运行的。这太慢了,所以我想并行化 for-each 循环中的语句,以便我为列表中的每个餐厅同时调用 Google Places API。理论上,响应时间应该是234ms + max(API call for Restaurant 1, ..., API call for Restaurant 7) = 234ms + 520ms = 754ms,因为对 Google API 的调用是并行进行的。
根据this link (Java 8: Parallel FOR loop),我应该可以像这样使用parallelStream()同时执行语句:
long startTime = System.currentTimeMillis();
restaurants.parallelStream().forEach(restaurant -> {
PlacesAPIResponse response = callGooglePlacesAPI(restaurant);
restaurant.setRating(response.getRating());
});
long endTime = System.currentTimeMillis();
System.out.println("Calling Google Places API took " + (endTime - startTime) + " milliseconds");
这似乎为每家餐厅并行调用 Google Places API,但现在每次调用 Google Places API 似乎都需要越来越多的时间。这是我的时间戳的输出:
getRestaurants() took 234 milliseconds
Took 335 milliseconds to call Google Places API for Restaurant 1
Took 337 milliseconds to call Google Places API for Restaurant 2
Took 671 milliseconds to call Google Places API for Restaurant 3
Took 742 milliseconds to call Google Places API for Restaurant 4
Took 1086 milliseconds to call Google Places API for Restaurant 5
Took 1116 milliseconds to call Google Places API for Restaurant 6
Took 1470 milliseconds to call Google Places API for Restaurant 7
Calling Google Places API took 1473 milliseconds
1734ms 比我预期的 754ms 大得多。我已经尝试过并行流以及 ExecutorService 来同时调用 Google Places API,但我似乎无法获得所需的响应时间。谁能指出我正确的方向?谢谢。
编辑:这是我对 ExecutorService 的尝试,根据这篇文章(Is there a easy way to parallelize a foreach loop in java?):
startTime = System.currentTimeMillis();
ExecutorService exe = Executors.newFixedThreadPool(2); // 2 can be changed of course
for (Restaurant restaurant : restaurants) {
exe.submit(() -> {
PlacesAPIResponse response = callGooglePlacesAPI(restaurant); // A call to the Google API should take 520ms for a given restaurant
restaurant.setRating(response.getRating());
});
}
exe.shutdown();
try {
exe.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
endTime = System.currentTimeMillis();
System.out.println("Calling Google Places API took " + (endTime - startTime) + " milliseconds");
return restaurants;
这是我的时间戳的输出:
getRestaurants() took 234 milliseconds
Took 464 milliseconds to call Google Places API for Restaurant 1
Took 575 milliseconds to call Google Places API for Restaurant 2
Took 452 milliseconds to call Google Places API for Restaurant 3
Took 420 milliseconds to call Google Places API for Restaurant 4
Took 414 milliseconds to call Google Places API for Restaurant 5
Took 444 milliseconds to call Google Places API for Restaurant 6
Took 422 milliseconds to call Google Places API for Restaurant 7
Calling Google Places API took 1757 milliseconds
这个方法的响应时间仍然是234ms + 1757 ms而不是234ms + 575ms,我不明白为什么。
【问题讨论】:
标签: java multithreading concurrency parallel-processing