这里是我必须快速运行的代码片段:
fillPricedServiceForLocation(location, doc, locale, services);
fillReviewsForLocation(location, doc, services);
两种方法如下:
private static void fillPricedServiceForLocation(Location location, LocationDocument doc,
Language locale, List<Long> services) {
if (doc.isPriceList()) {
String locationId = doc.getLocationId();
try {
new PricesRepository().findServiceForLocation(locationId, services)
.ifPresent(foundService -> {
String serviceId = foundService.getServiceId();
final LocationServices locationServices = new LocationServices();
locationServices.setId(Integer.valueOf(serviceId));
locationServices.setPrice(BigDecimal.valueOf(foundService.getPrice()));
locationServices.setCurrency(foundService.getCurrency());
ServiceName serviceName = ServiceNameProvider.getServiceName(serviceId);
locationServices.setName(serviceName.getName(locale));
location.setServices(locationServices);
});
} catch (Exception e) {
log.error("Error when trying to retrieve last review for location {}", locationId,
e);
}
}
}
private static void fillReviewsForLocation(Location location, LocationDocument doc,
List<Long> services) {
String locationId = doc.getLocationId();
try {
LocationReviews locationReviews = new LocationReviews();
locationReviews.setCount(doc.getReviewsCount());
locationReviews.setScore(doc.getReviewsScore());
new ReviewsRepository().findReview(locationId, services).ifPresent(
foundReview -> locationReviews.setReview(reviewDocumentToJsonModel(foundReview)));
location.setReviews(locationReviews);
} catch (Exception e) {
log.error("Error when trying to retrieve last review for location {}", locationId, e);
}
}
他们调用两个不同的repositiories,如果他们找到了什么,他们会处理它并更新作为参数 location 传递。是否可以对这两个方法调用进行并行化,以便同时处理它们?尝试使用CompleteableFuture但无法使其运行 - 对异步编程没有多少经验。
答案 0 :(得分:0)
你可以在两个不同的线程和每个线程的run()方法中编写一个函数。然后使用ExecutorService.submit(threadOne)和ExecutorService.submit(threadTwo)并行执行它。
答案 1 :(得分:0)
使用CompletableFutures,你应该能够做到:
CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> fillPricedServiceForLocation(location, doc, locale, services));
CompletableFuture<Void> task2 = CompletableFuture.runAsync(() -> fillReviewsForLocation(location, doc, services)));
task1.join();
task2.join();
这将在新的单独线程(JVM用于这些事情的默认fork-join池)中并行运行这两个任务。主线程将等待两者完成(使用join()
。如果您愿意,可以在调用join()
之前执行其他操作。
如果两者都在更新同一个对象(Location
),请确保您的更新是线程安全的。让方法单独返回信息然后更新主线程中的公共数据结构可能更安全。这也比引入不必要的synchronized
块更快。
如果您想从CompletableFuture
返回一些值,可以使用supplyAsync()
代替runAsync()
轻松完成,这样您就可以将值返回给任务。 (它的类型不会是CompletableFuture<Void>
,而是CompletableFuture<LocationReviews>
和CompletableFuture<LocationServices>
。)
因此,例如,方法可能是这样的:
CompletableFuture<LocationServices> servicesTask = CompletableFuture.supplyAsync(() -> getPricedServiceForLocation(doc, locale, services));
CompletableFuture<LocationReviews> reviewsTask = CompletableFuture.supplyAsync(() -> getReviewsForLocation(doc, services)));
location.setServices(servicesTask.get());
location.setReviews(reviewsTask.get());
您不需要将Location作为参数传递给这些方法,它们只是异步地为您检索信息。
private static LocationServices getPricedServiceForLocation(LocationDocument doc, Language locale, List<Long> services) {
...
}
private static LocationReviews getReviewsForLocation(LocationDocument doc, List<Long> services) {
...
}