Completable Future Getting Started (First Future)

Future

Interface introduced in Java 5. Used to model future results that may be available at some point. Model asynchronous processing and provide a reference to the result when processing is complete. Future allows the calling thread to continue another process instead of waiting for the result. Java8 In Action

What makes me happy to use Future

  1. No more waiting for time-consuming processing
  2. Easier to work with than low layer threads

how to use

Wrap the time-consuming process in the Callable object and pass it to ExecutorSerice.

ExecutorService executor = Executors.newCachedThreadPool();
//Pass the task to the thread pool
Future<Double> future = executor.submit(new Callable<Double>() {
        public Double call() { //Perform processing in another thread
            return doSomeLongComputation();
               }});
doSomethingElse();

Use Future's get method to get the result of asynchronous processing. In actual use, you need to catch multiple exceptions. Future.get

Double value = future.get();
Double result = future.get(1, TimeUnit.SECONDS); //Specify the timeout time

Things to consider in asynchronous processing using Future

"If the wrapped process doSomeLongComputation never returns a result "

By using the following method You can check if the asynchronous process is complete

Then

"When the result of FuturedoSomeLongComputation is used by another FuturedoSomeMoreLongComputation"

What should i do?

The confusing point is that there is an execution order between asynchronous processes. In executing the second future It is necessary to actively check the result of the first futuredoSomeLongComputation. </ del>

ExecutorService executor = Executors.newCachedThreadPool();
Future<Double> future = executor.submit(new Callable<Double>() {
    public Double call() {
        return doSomeLongComputation();
    }});

//Monitor until the processing of the first future is completed
do {
    System.out.println("in while");
} while(!future.isDone());

Future<Double> futureSecond = executor.submit(new Callable<Double>() {
    public Double call() {
        try {
            return doSomeLongMoreComputation(future.get());
        } catch (InterruptedException | ExecutionException e) {
            return 0.0;
        }
    }});

It is possible to write a process that has an order between asynchronous processes without using a while statement.

long start = System.nanoTime();
ExecutorService executor = Executors.newCachedThreadPool();
System.out.println(String.format("before future elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
//1st future
Future<Double> future = executor.submit(new Callable<Double>() {
    public Double call() {
        return doSomeLongComputation();
    }});
System.out.println(String.format("after future elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
//Second future
Future<Double> futureSecond = executor.submit(new Callable<Double>() {
    public Double call() {
        try {
            System.out.println(String.format("before future.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
            double value = future.get(); //Call the first future
            System.out.println(String.format("after future.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
            //Use the processing result of the first future
            return doSomeLongMoreComputation(value);
        } catch (InterruptedException | ExecutionException e) {
            return 0.0;
        }
    }});

try {
    System.out.println(String.format("before futureSecond.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
    //Call the second future here
    double d = futureSecond.get();
    System.out.println(String.format("after futureSecond.get elapsed time: %d msecs", (System.nanoTime()-start)/1_000_000));
} catch (InterruptedException | ExecutionException e) {
    System.out.println(e);
}

result The processing of the second future is blocked until the processing of the nested future is completed (∵ The second future uses the processing result of the first future).

before future elapsed time: 3 msecs
doSomeLongComputation called 
after future elapsed time: 25 msecs
before futureSecond.get elapsed time: 26 msecs <-Start of the second future
before future.get elapsed time: 26 msecs <-Start of the first nested future
doSomeLongComputation: 10
after future.get elapsed time: 10027 msecs <-End of the first nested future
doSomeLongMoreComputation called 
doSomeLongMoreComputation: 11
after futureSecond.get elapsed time: 20029 msecs <-End of the second future

What I want to achieve in the end is ...

  1. Combine two asynchronous processes
  2. Wait for all the processing performed by the Future chunk to complete
  3. Wait for the completion of only the earliest executed task in the future chunk
  4. Programmatically complete Future
  5. Respond to the completion of Future
  6. Notify when processing is completed
  7. Execute processing using Future result instead of waiting for processing result

these, Using the features of ** Java8 **, Use CompletableFuture if you want to do it in a declarative way.

Recommended Posts

Completable Future Getting Started (First Future)
Getting Started with Ruby
Getting Started with Docker
Java 8 Completable Future Survey
Getting Started with Doma-Transactions
Getting Started with Doma-Annotation Processing
Getting Started with Java Collection
Getting Started with Java Basics
Getting Started with Spring Boot
Getting Started with Ruby Modules
Getting Started with Java_Chapter 5_Practice Exercises 5_4
[Google Cloud] Getting Started with Docker
Getting started with Java lambda expressions
Getting Started with Docker with VS Code
CompletableFuture Getting Started 2 (Try to make CompletableFuture)
<First post> I started studying Ruby