1. 程式人生 > 其它 >高併發程式設計-非同步-JDK8-CompletableFuture

高併發程式設計-非同步-JDK8-CompletableFuture

高併發程式設計-非同步-JDK8-CompletableFuture

一、CompletableFuture簡介

  簡單任務處理,可以使用Future,在實際的開發過程中,可以非同步提交多個任務,業務邏輯也可能依賴,並行聚合的關係,此時用Futrue將會很麻煩。

  CompletableFuture是Future的補充和擴充套件,實現了任務的編排能力,在開發過程中可以使我們輕鬆組織不同任務的順序,規則。

二、應用場景

  依賴關係:

  1. thenApply 把前面非同步任務的結果,交給後面的function
  2. thenCompose()用來連線兩個有依賴關係的任務,結果由第二個任務返回

描述and聚合關係:

  1. thenCombine:任務合併,有返回值
  2. thenAccepetBoth:兩個任務執行完成後,將結果交給thenAccepetBoth消耗, 無返回值。
  3. runAfterBoth:兩個任務都執行完成後,執行下一步操作(Runnable) 

  描述OR聚合關係:

  1. applyToEither:兩個任務誰執行的快,就使用那一個結果,有返回值。
  2. acceptEither: 兩個任務誰執行的快,就消耗那一個結果,無返回值。 
  3. runAfterEither: 任意一個任務執行完成,進行下一步操作(Runnable)

三、非同步操作

  CompletableFuture 提供了四個靜態方法來建立一個非同步操作:

//runAsync 方法以Runnable函式式介面型別為引數,沒有返回結果 
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
//supplyAsync 方法Supplier函式式介面型別為引數,返回結果型別為U;Supplier 介面的 get() 方法是有返回值的(會阻塞)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

  如果沒有指定執行緒池,會使用ForkJoinPool.commonPool() 作為它的執行緒池執 行非同步程式碼,預設情況下 CompletableFuture 會使用公共的 ForkJoinPool 執行緒池,這個執行緒池 預設建立的執行緒數是 CPU 的核數(也可以通過 JVM option:- Djava.util.concurrent.ForkJoinPool.common.parallelism 來設定 ForkJoinPool 執行緒 池的執行緒數)。如果所有 CompletableFuture 共享一個執行緒池,那麼一旦有任務執行 一些很慢的 I/O 操作,就會導致執行緒池中所有執行緒都阻塞在 I/O 操作上,從而造成執行緒 飢餓,進而影響整個系統的效能。所以,強烈建議你要根據不同的業務型別建立不同的 執行緒池,以避免互相干擾。

public class CompletableFutureDemo {
    final static CountDownLatch latch = new CountDownLatch(1);
    @SneakyThrows
    public static void main(String[] args) {
        CompletableFuture<String> stringCompletableFuture = supplyAsync();

        System.out.println(stringCompletableFuture.get());

        System.out.println(Thread.currentThread().getName());
        latch.await();

    }

    /**
     * 無返回結果的非同步執行緒
     */
    public static   void runAsync(){
        System.out.println(Thread.currentThread().getName());

        Runnable runnable=()-> {
            System.out.println("非同步執行緒執行,不需要返回結果");
            System.out.println(Thread.currentThread().getName());
            latch.countDown();
        };
        CompletableFuture.runAsync(runnable);
    }
    /**
     * 有返回結果的非同步執行緒
     */
    public static   CompletableFuture<String> supplyAsync(){
        System.out.println(Thread.currentThread().getName());


        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("執行非同步任務,有返回結果!");
            try {
                Thread.sleep(4000);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello world";

        });
        latch.countDown();
         return future;
    }

四、獲取結果

   join()和get()方法都是用來獲取CompletableFuture非同步之後的返回值。join()方法丟擲的是 uncheck異常(即未經檢查的異常),不會強制開發者丟擲。get()方法丟擲的是經過檢查的異 常,ExecutionException, InterruptedException 需要使用者手動處理(丟擲或者 try catch)

  對結果的處理方式程式碼 明天繼續,今天太累了