Java 8 Completable Future Survey

Complex threading in Java

Java has a Thread class from the beginning, but instantiation was heavy and subtle.

Executor was introduced from JDK5, making it easier to do WorkerThread-like things, and the number of Lock-type classes has increased, making it more convenient. In addition, the introduction of Future has made it easier to receive processing results. However, if you call Future.get (), the call Thread will block, so you have to write something that is not essential, such as doing it with another Thread.

Completable Future was introduced from Java8, and it seems that more complicated Thread processing can be performed, so I will investigate it.

Prerequisite knowledge

I don't think you can understand it unless you understand Function, Consumer, and Supplier, which were also introduced in Java 8. I wrote an article below, so please refer to it. Investigation of Function, Consumer, Supplier, Predicate of Java8

Returns a value as a result of processing and uses it for another processing

Since it is the Supplier that returns a certain value and the Consumer that receives and processes the value, combine the two.

CompletableFuture.supplyAsync (Supplier) returns an instance of CompletableFuture while processing the Supplier asynchronously. In CompletableFuture.thenAcceptAsync (Consumer), when the processing of CompletableFuture instance is completed, pass the return value and execute Consumer processing.

public void SupplyAndConsume() {
    Supplier<Integer> initValueSupplier = () -> 100;
    Consumer<Integer> valueConsumer = value -> System.out.println(value);

    CompletableFuture<Void> future =
            CompletableFuture.supplyAsync(initValueSupplier)
            .thenAcceptAsync(valueConsumer);
}

Processing result

100

The result of the process is to return a certain value, convert it, and use it for another process.

It is the Supplier that returns a certain value, the Function that converts it, and the Consumer that receives it and processes it.

Basically the same as the previous pattern, but with CompletableFuture.thenApplyAsync (Function), execute the Function processing while passing the value of the result of CompletableFuture.

public void SupplyAndExecuteAndConsume() {
    Supplier<Integer> initValueSupplier = () -> 100;
    Function<Integer, Integer> multiply = value -> value * 2;
    Consumer<Integer> valueConsumer = value -> System.out.println(value);

    CompletableFuture<Void> future =
            CompletableFuture.supplyAsync(initValueSupplier)
            .thenApplyAsync(multiply)
            .thenAcceptAsync(valueConsumer);
}

Processing result

200

Perform one process in multiple threads and use the first result to perform another process

Returns the result processed by Supplier and processes using the value received by Consumer. CompletableFuture.acceptEitherAsync (CompletableFuture, Consumer) can be used to perform Consumer processing using the one that gives the result first.

public void RaceAndConsume() {
    Supplier<Integer> initValueSupplier = () -> 100;
    Supplier<Integer> anotherValueSupplier = () -> 200;
    Consumer<Integer> valueConsumer = value -> System.out.println(value);

    CompletableFuture<Integer> future1 =
            CompletableFuture.supplyAsync(initValueSupplier);
    CompletableFuture<Integer> future2 =
            CompletableFuture.supplyAsync(anotherValueSupplier);

    future1.acceptEitherAsync(future2, valueConsumer);
}
100 or 200

Perform one process in multiple threads, use the first obtained result to perform another process, and use the result to perform another process.

public void RaceAndConsume() {
    Supplier<Integer> initValueSupplier = () -> 100;
    Supplier<Integer> anotherValueSupplier = () -> 200;
    Function<Integer, Integer> multiply = value -> value * 2;
    Consumer<Integer> valueConsumer = value -> System.out.println(value);

    CompletableFuture<Integer> future1 =
            CompletableFuture.supplyAsync(initValueSupplier);
    CompletableFuture<Integer> future2 =
            CompletableFuture.supplyAsync(anotherValueSupplier);

    future1.applyToEitherAsync(future2, multiply)
            .thenAcceptAsync(valueConsumer);
}
200 or 400

If you want a complete understanding of synchronized

Explanation of synchronized and typical error example I wrote, so please check it out as well. Experience shows that about 70% of people are wrong.

Recommended Posts

Java 8 Completable Future Survey
Completable Future Getting Started (First Future)
Java
Java
Survey of Java 8 Function, Consumer, Supplier, Predicate
About the number of threads of Completable Future