bhylu.com

Advertisements

Java Separate a Task from Its Execution Policy

An executor manages how tasks are run. A Future represents an eventual result and lets the caller observe completion or failure.

Understand the idea

Submitting a Callable returns a Future whose get operation waits for the task’s result and can report a wrapped task failure. The executor also needs a lifecycle policy so worker threads do not outlive the application accidentally. In this course’s Java 21 baseline, ExecutorService is AutoCloseable, allowing a small scoped example. A production service often owns a longer-lived executor and closes it at a broader boundary.

Run it locally

Use a local JDK 21 or newer. Save the complete example as Main.java in a separate lab folder, then compile and run it with the commands below. Java examples do not run in Bhylu’s browser playground. The -ea option enables assertion checks used by some lessons.

JDK and terminal setup

javac --release 21 -encoding UTF-8 -d out Main.java
java -ea -cp out Main

A worked example

Java 21+ · Main.java

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws Exception {
        try (ExecutorService executor = Executors.newFixedThreadPool(2)) {
            Future<Integer> first = executor.submit(() -> 4 * 3);
            Future<Integer> second = executor.submit(() -> 5 * 2);
            System.out.println(first.get() + second.get());
        }
    }
}

Expected output

22

The two tasks return independent integer results, and the caller combines them after get has obtained each result. The code does not assume which worker runs first. Closing the executor at the end makes its lifetime visible. get can block, so a real request boundary may need timeouts and cancellation rather than an indefinite wait.

Check the official Java documentation for detailed contracts and supported options.