簡體   English   中英

使用CompleteableFuture執行兩個異步方法

[英]Using CompleteableFuture for executing two methods async

這是我必須使運行更快的代碼的片段:

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);
    }
}

他們調用了兩個不同的存儲庫,如果找到了東西,他們會處理它並更新作為參數位置傳遞的信息。 是否可以並行處理這兩個方法調用,以便同時處理它們? 使用CompleteableFuture進行了嘗試,但無法使其運行-沒有太多異步編程經驗。

您可以使用兩個不同的線程,並在每個線程的run()方法中編寫一個函數,然后使用ExecutorService.submit(threadOne)和ExecutorService.submit(threadTwo)並行執行它。

使用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()之前執行其他操作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) {
  ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM