Wie verwende ich die asynchrone Orchestrierung von CompletableFuture?

Überblick:

Bei der Bestellungsübermittlungsfunktion müssen wir uns um viele Dinge kümmern, wie zum Beispiel: Ändern des Lagerbestands, Berechnen von Rabattaktionsinformationen, Hinzufügen und Abziehen von Mitgliedspunkten, Online-Zahlung, Betragsberechnung, Generieren von Produktbestellungen, Generieren von Finanzinformationen, Löschen von Einkäufen Karren usw. Wenn alle diese Funktionen serialisiert sind, dauert es lange, insbesondere wenn große Datenmengen gleichzeitig vorliegen, und es kann zu verschiedenen Anomalien wie Serverabstürzen kommen.

Das Aufkommen der asynchronen Orchestrierung von CompletableFuture löst die oben genannte Situation vollständig, und diese Funktionen können grundsätzlich parallel verarbeitet werden. Was ist also die asynchrone Orchestrierung von CompletableFuture?

  • Die asynchrone Orchestrierung von CompletableFuture ist ein in Java 8 eingeführtes asynchrones Programmiertool, das eine bequeme Möglichkeit zur Bearbeitung asynchroner Aufgaben bietet.

  • Unter asynchroner Orchestrierung versteht man die Kombination und Ausführung mehrerer asynchroner Aufgaben gemäß einer bestimmten Reihenfolge oder Abhängigkeitsbeziehung, um eine komplexere Geschäftslogik zu implementieren.

  • Die CompletableFuture-Klasse implementiert die Future-Schnittstelle, sodass Sie wie zuvor weiterhin Ergebnisse durch getMethodenblockierung oder
    Abfrage erhalten können, diese Methode wird jedoch nicht empfohlen.

  • Sowohl CompletableFuture als auch FutureTask gehören zur Implementierungsklasse der Future-Schnittstelle und beide können das Ausführungsergebnis des Threads abrufen.

Wie im Bild gezeigt:
Fügen Sie hier eine Bildbeschreibung ein

Bei der Orchestrierung asynchroner Vorgänge stellt CompletableFuture Methoden wie thenApply, thenAccept, thenRun usw. bereit, mit denen Sie einige Vorgänge nach Abschluss des asynchronen Vorgangs ausführen können. Diese Methoden werden unten hervorgehoben.

1. Erstellen Sie ein asynchrones Objekt

1 Grundlegende Methode

CompletableFuture bietet vier statische Methoden zum Erstellen einer asynchronen Operation.

static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executorexecutor)

1. runXxxx gibt kein Ergebnis zurück und SupplyXxx kann ein Rückgabeergebnis erhalten.
2. Sie können einen benutzerdefinierten Thread-Pool übergeben, andernfalls verwenden Sie den Standard-Thread-Pool.

2 Beispiel:

  public static void runAsync() {
    
    
        System.out.println("runAsync....start....");
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果:" + i);
        }, executorService);
        System.out.println("runAsync....end....");
    }

2. Die Rückrufmethode, wenn die Berechnung abgeschlossen ist

1 Grundlegende Methode

public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action):
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable>action);
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable>action, Executor executor):
public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn);
  • whenComplete kann normale und abnormale Berechnungsergebnisse verarbeiten und verarbeitet in Ausnahmefällen abnormale Bedingungen.
  • Der Unterschied zwischen whenComplete und whenCompleteAsync:

whenComplete: Der Thread, der die aktuelle Aufgabe ausführt, führt die Aufgabe aus, die weiterhin whenComplete ausführt.
whenCompleteAsync: dient dazu, die Aufgabe von whenCompleteAsync auszuführen, um sie weiterhin zur Ausführung an den Thread-Pool zu senden

Die Methode endet nicht mit Async, was bedeutet, dass Action denselben Thread zur Ausführung verwendet und Async möglicherweise andere Threads
zur Ausführung verwendet (wenn es denselben Thread-Pool verwendet, kann es auch für die Ausführung durch denselben Thread ausgewählt werden).

2 Beispiele

public static void suplyAsync() {
    
    
        try {
    
    
            System.out.println("suplyAsync....start....");
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 0;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).whenComplete((res, err) -> {
                System.out.println("异步任务完成了..结果.." + res);
                System.out.println("异步任务完成了..异常.." + err);
            }).exceptionally(throwable -> {
                System.out.println("发生了异常.返回默认值....");
                return 10;
            });
            System.out.println("最终结果:" + future.get());
            System.out.println("suplyAsync....end....");
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

Drei, Handle-Methode

1 Grundlegende Methode

public <U> Completionstage<U> handle(BiFunction<? super T, Throwable,? extends U> fn);
public <U> Completionstage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U>fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U>
fn,Executor executor);

Wie Complete kann es eine abschließende Verarbeitung des Ergebnisses durchführen (Ausnahmen behandeln) und den Rückgabewert ändern.

2 Beispiele

//完成后的处理
public static void suplyAsyncHandler() {
    
    
    try {
    
    
        System.out.println("suplyAsyncHandler....start....");
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果:" + i);
            return i;
        }, executorService).handle((res, err) -> {
            if(res != null){
                System.out.println("res:" + res);
                return res * 2;
            }
            if (err != null){
                System.out.println("err:" + err);
                return 0;
            }
            return res;
        });
        System.out.println("最终结果====" + future.get());
        System.out.println("suplyAsyncHandler....end....");
    } catch (Exception e) {
    
    
        throw new RuntimeException(e);
    }
}

Viertens Thread-Serialisierungsmethode

1 Grundlegende Methode

public <U> CompletableFuture<u> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<u> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor)

public CompletionStage<Void> thenAccept(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executorexecutor);

public CompletionStage<Void> thenRun(Runnable action);
public Completionstage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
  • thenApply-Methode: Wenn ein Thread von einem anderen Thread abhängt, wird das von der vorherigen Aufgabe zurückgegebene Ergebnis abgerufen und der
    Rückgabewert der aktuellen Aufgabe zurückgegeben.
  • thenAccept-Methode: Verarbeitungsergebnisse verbrauchen. Empfangen Sie das Verarbeitungsergebnis der Aufgabe, verbrauchen Sie die Verarbeitung und geben Sie kein Ergebnis zurück.
  • thenRun-Methode: Solange die obige Aufgabe ausgeführt wird, wird thenRun ausgeführt, und erst nachdem die Aufgabe verarbeitet wurde, wird die
    Folgeoperation von thenRun ausgeführt
  • Bei Async wird es standardmäßig asynchron ausgeführt. Das Gleiche wie vorher.

Alle vorangehenden Aufgaben müssen erfolgreich abgeschlossen werden.

Function<? super T,? extends U>
T:上一个任务返回结果的类型
U:当前任务的返回值类型

2 Beispiele

//---多个任务串行执行-----------------------------------------------------
    //ThenApplyAsync 可以获取上次的结果,有返回值
    public static void suplyAsyncThenApplyAsync() {
    
    
        try {
    
    
            System.out.println("suplyAsyncThenRun....start....");
            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenApplyAsync((res) -> {
                System.out.println("任务1的结果是...." + res);
                System.out.println("启动任务2..........");
                return res;
            }, executorService);
            System.out.println("最终结果是:" + future);
            System.out.println("suplyAsyncThenRun....end....");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    //thenAcceptAsync 可以获取上次的结果,没返回值
    public static void suplyAsyncThenAcceptAsync() {
        try {
            System.out.println("suplyAsyncThenRun....start....");
            CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenAcceptAsync((res) -> {
                System.out.println("任务1的结果是...." + res);
                System.out.println("启动任务2..........");
            }, executorService);
            System.out.println("suplyAsyncThenRun....end....");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //thenRunAsync 不能获取上次任务的结果,没返回值
    public static void suplyAsyncThenRun() {
        try {
            System.out.println("suplyAsyncThenRun....start....");
            CompletableFuture.supplyAsync(() -> {
                System.out.println("当前线程:" + Thread.currentThread().getId());
                int i = 10 / 2;
                System.out.println("计算结果:" + i);
                return i;
            }, executorService).thenRunAsync(() -> {
    
    
                System.out.println("启动任务2..........");
            }, executorService);
            System.out.println("suplyAsyncThenRun....end....");
        } catch (Exception e) {
    
    
            throw new RuntimeException(e);
        }
    }

5. Kombination zweier Aufgaben – beide müssen erledigt werden

1 Grundlegende Einführung

public <U,V> CompletableFuture<V> thenCombine(CompletionStage<? extends U> other ,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletableFuture<v> thenCombineAsync(CompletionStage<? extends U> otherBiFunction<? super T,? super u,? extends V> fn);
public <U,V> CompletableFuture<V> thenCombineAsync(CompletionStage<? extends U> other ,BiFunction<? super T,? super U,? extends V> fn, Executor executor);

public <U> CompletableFuture<Void> thenAcceptBoth(Completionstage<? extends U> other .BiConsumer<? super T,? super U> action);
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other .BiConsumer<? super T, ? super U> action) ;
public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other ,BiConsumer<? super t. ? super Us action. Executor executor):

public CompletableFuture<Void> runAfterBoth(CompletionStage<?> other.Runnable action);
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other .Runnable action):
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> otherRunnable action,
Executor executor  ;

Beide Aufgaben müssen abgeschlossen sein, um diese Aufgabe auszulösen.

  • thenCombine: Kombinieren Sie zwei Futures, erhalten Sie die Rückgabeergebnisse der beiden Futures und geben Sie den Rückgabewert der aktuellen Aufgabe zurück
  • thenAcceptBoth: Kombinieren Sie zwei Futures, erhalten Sie die Rückgabeergebnisse der beiden zukünftigen Aufgaben und verarbeiten Sie die Aufgaben dann ohne
    Rückgabewert.
  • runAfterBoth: Kombinieren Sie zwei Futures. Es ist nicht erforderlich, die Ergebnisse der Zukunft abzurufen. Die Aufgabe muss erst verarbeitet werden, nachdem die beiden Futures die
    Verarbeitung der Aufgabe abgeschlossen haben.

2 Beispiele

//---任务组合-----------------------------------------------------
public static void thenCombineAsync() throws ExecutionException, InterruptedException {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        CompletableFuture<Integer> future3 = future1.thenCombineAsync(future2, (res1, res2) -> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程2结果....." + res2);
            System.out.println("线程3开始.....");
            return res1 + res2;
        }, executorService);

        System.out.println("线程3的结果是...." + future3.get());

    }

    public static void thenAcceptBothAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.thenAcceptBothAsync(future2, (res1, res2)-> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程2结果....." + res2);
            System.out.println("线程3开始.....");
        }, executorService);

    }

    public static void runAfterBothAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.runAfterBothAsync(future2, ()-> {
    
    
            System.out.println("线程3开始.....");
        }, executorService);

    }

6. Kombination zweier Aufgaben – mit einer abschließen

1 Funktionseinführung

public <U> CompletableFuture<u> applyToEither(
CompletionStage<? extends T> other , Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other , Function<? super T, U> fn);
public <U> CompletableFuture<U> applyToEitherAsync(CompletionStage<? extends T> other , Function<? super T, U> fn,Executor executor):

public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other , Consumer<? super T> action);
public CompletableFuture<Void> acceptEitherAsync
CompletionStage<? extends T> other, Consumer<? super T> action);
public CompletableFuture<void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action,Executor executor ;

public CompletableFuture<Void> runAfterEither (CompletionStage<?> other ,Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other ,Runnable action);
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other ,Runnable action,
Executor executor);

Wenn eine der zukünftigen Aufgaben in den beiden Aufgaben abgeschlossen ist, wird die Aufgabe ausgeführt.

  • applyToEither: Eine der beiden Aufgaben wird ausgeführt, erhält ihren Rückgabewert, verarbeitet die Aufgabe und hat einen neuen Rückgabewert.
  • AcceptEither: Eine der beiden Aufgaben wird ausgeführt, erhält ihren Rückgabewert, verarbeitet die Aufgabe und es gibt keinen neuen Rückgabewert.
  • runAfterEither: Eine der beiden Aufgaben ist abgeschlossen, es besteht keine Notwendigkeit, das Ergebnis der Zukunft abzurufen, die Aufgabe zu verarbeiten und es gibt keinen Rückgabewert
    .

2 Beispiele

 //---任务组合--一个都完成---------------------------------------------------
    public static void applyToEitherAsync() throws ExecutionException, InterruptedException {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        CompletableFuture<Integer> future3 = future1.applyToEitherAsync(future2, (res1) -> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程3开始.....");
            return res1;
        }, executorService);

        System.out.println("线程3的结果是...." + future3.get());

    }

    public static void acceptEitherAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.acceptEitherAsync(future2, (res1)-> {
    
    
            System.out.println("线程1结果....." + res1);
            System.out.println("线程3开始.....");
        }, executorService);

    }

    public static void runAfterEitherAsync() {
    
    
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1:" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("计算结果1:" + i);
            return i;
        }, executorService);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2:" + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("计算结果2:" + i);
            return i;
        }, executorService);

        future1.runAfterEitherAsync(future2, ()-> {
    
    
            System.out.println("线程3开始.....");
        }, executorService);

    }

Sieben, Multitasking-Kombination

1 Funktionseinführung

public static CompletableFuture<Void> allof(CompletableFuture<?>... cfs);
public static CompletableFuture<0bject> anyof(CompletableFuture<?>... cfs);
  • allof: Warten Sie, bis alle Aufgaben abgeschlossen sind
  • anyof: solange eine Aufgabe erledigt ist

2 Beispiele

 public static void allOf() throws ExecutionException, InterruptedException {
    
    
	CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1执行");
            return 10 / 2;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行");
            return "hello";
        }, executor);
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02,
                (result1, result2) -> {
                    System.out.println("任务3执行");
                    System.out.println("任务1返回值:" + result1);
                    System.out.println("任务2返回值:" + result2);
                    return "任务3返回值";
                }, executor);
        System.out.println(future03.get());


        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02, future03);
        allOf.get();// 阻塞等待所有任务完成
  }


public static void anyOf() throws ExecutionException, InterruptedException {
    
    
	CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1执行");
            return 10 / 2;
        }, executor);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2执行");
            return "hello";
        }, executor);
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02,
                (result1, result2) -> {
                    System.out.println("任务3执行");
                    System.out.println("任务1返回值:" + result1);
                    System.out.println("任务2返回值:" + result2);
                    return "任务3返回值";
                }, executor);
        System.out.println(future03.get());


        CompletableFuture<Void> anyOf= CompletableFuture.allOf(future01, future02, future03);
        anyOf.get();// 阻塞等待任一任务完成,返回值是执行成功的任务返回值
  }

Acht, Quellcode herunterladen

https://gitee.com/charlinchenlin/koo-erp

Supongo que te gusta

Origin blog.csdn.net/lovoo/article/details/130861594
Recomendado
Clasificación