Java 函數(shù)式編程 之組合式異步編程

我們這一篇介紹一下java8中的異步編程,其實在java5的時候,F(xiàn)uture就已經(jīng)被引入了,下面我們用一個例子說明下Future的簡單使用,
public class FutureExample {

public static void main(String[] arg) throws ExecutionException, InterruptedException, TimeoutException {

    ExecutorService executorService = new ThreadPoolExecutor(2,10,30, TimeUnit.MINUTES,new ArrayBlockingQueue<>(10));
    Future<Integer> result = executorService.submit(() -> doSomething());
    System.out.println(result.get(10,TimeUnit.SECONDS));

}


public static Integer doSomething() throws InterruptedException {
    TimeUnit.SECONDS.sleep(7);//模擬時間占用
    return 666;

}}

這邊我們使用了future來異步獲得返回值,那我們考慮一下,如果我們現(xiàn)在有多個任務(wù),任務(wù)之間還存在依賴關(guān)系的話,那么我們采用Future實現(xiàn),代碼是怎么樣的呢,我們難免要使用Future提供給我們的isDone來判斷,這樣代碼就會變得不簡潔,接下來我們就引入一個新的類,CompleteFuture 來解決future不能解決的復(fù)雜需求.

我們這邊假設(shè)這樣一個場景,收銀員使用一套系統(tǒng)來獲取輸入的水果的打折之后的價格,按照一般的代碼寫法:

 public void delay() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
  }
       /**
 * get the product price in synchronized way
 *
 * @param product
 * @return
 * @throws InterruptedException
 */
public double getPrice(String product) throws InterruptedException {
    return calculatePrice(product);
}


/**
 * calculate the price.
 *
 * @param price
 * @return
 * @throws InterruptedException
 */
public double calculatePrice(String price) throws InterruptedException {
    delay();//模擬數(shù)據(jù)庫等操作
    return new Random(100).nextDouble() * 100;//模擬價格
}

 /**
 * get the latest discount info
 *
 * @param product
 * @return
 */
public double getLatestDiscountInfo(String product) throws InterruptedException {
    TimeUnit.SECONDS.sleep(2);
    return new Random(100).nextDouble();
}

那我們?nèi)绾问褂肅ompleteFuture來進(jìn)行改造呢,看下面

   public CompletableFuture<Double> getPriceAsync(String product) {
    CompletableFuture<Double> futureResult = new CompletableFuture<>();
    new Thread(() -> {
        try {
            double price = calculatePrice(product);
            futureResult.complete(price);
        } catch (InterruptedException e) {
            futureResult.completeExceptionally(e);
        }
    }).start();
    return futureResult;
}

看了一下這代碼,感覺有點雜,單獨(dú)開啟一個線程來,如果請求很多,那么大量的線程將占用大量的資源,一種解決的辦法是采用我們自己手工創(chuàng)建的線程池的方法,還有一種就是采用CompleteFuture給我們提供的靜態(tài)方法,如下 :

    /**
 * Returns a new CompletableFuture that is asynchronously completed
 * by a task running in the given executor with the value obtained
 * by calling the given Supplier.
 *
 * @param supplier a function returning the value to be used
 * to complete the returned CompletableFuture
 * @param executor the executor to use for asynchronous execution
 * @param <U> the function's return type
 * @return the new CompletableFuture
 */
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                   Executor executor) {
    return asyncSupplyStage(screenExecutor(executor), supplier);
}

改造之后:

 public CompletableFuture<Double> getPriceAsync(String product) {
    //we can refactor above code to below
    CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {
        Double v = null;
        try {
            v = calculatePrice(product);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return v;
    }, threadExecutor);
    return future;
}

再深入CompleteFuture, 我們觀察到其內(nèi)部還提供這些函數(shù)。

Screen Shot 2019-04-10 at 11.17.01 PM.png

我們可以猜測到,其功能可能遠(yuǎn)遠(yuǎn)不止我們上面介紹的那些,下面我們就簡單的使用下其中一個方法。

  public static void testCombine() throws ExecutionException,InterruptedException {

    PriceService priceService = new PriceService();

    Future<Double> future = CompletableFuture.supplyAsync(() -> {
        return priceService.getPrice("apple");
    }).thenCombine(CompletableFuture.supplyAsync(() -> {
                return priceService.getPrice("Grape");
            }
    ), (priceOne, priceTwo) -> priceOne + priceTwo);


        System.out.println("The sum of the price of  apple and Grade is" +             future.get());


}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容