Java CompletableFuture thenRun() Method

The CompletableFuture class in Java provides the thenRun() method to run a specified action when the CompletableFuture completes.

Introduction

The CompletableFuture.thenRun() method is used to execute a Runnable action after a CompletableFuture completes, regardless of the result. This is useful for running tasks that do not depend on the result of the CompletableFuture.

thenRun Method Syntax

The syntax for the thenRun method is as follows:

public CompletableFuture<Void> thenRun(Runnable action)
  • The method takes a single parameter action of type Runnable, which represents the action to run when the CompletableFuture completes.
  • The method returns a CompletableFuture<Void> that is completed when the action is finished.

Examples

Example 1: Logging Completion

In a web application, you might want to log a message when a CompletableFuture completes, regardless of its result.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class ThenRunExample {
    public static void main(String[] args) {
        // Create a CompletableFuture that completes with a string
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello, world!");

        // Log a message when the future completes using thenRun
        future.thenRun(() -> System.out.println("Future completed"));

        // Wait for the future to complete
        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

Output:

Future completed

Example 2: Task Management System

In a task management system, you might want to perform a cleanup operation after a task is completed.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class TaskManagementSystem {
    public static void main(String[] args) {
        // Create a CompletableFuture that completes with a task
        CompletableFuture<Task> taskFuture = CompletableFuture.supplyAsync(() -> new Task("Complete project report", 2));

        // Perform cleanup operation when the task completes using thenRun
        taskFuture.thenRun(() -> System.out.println("Cleanup after task completion"));

        // Wait for the task to complete
        try {
            taskFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

class Task {
    private String description;
    private int priority;

    public Task(String description, int priority) {
        this.description = description;
        this.priority = priority;
    }

    @Override
    public String toString() {
        return description + " (Priority: " + priority + ")";
    }
}

Output:

Cleanup after task completion

Example 3: Updating a Status

In an application, you might want to update the status of a process once a CompletableFuture completes, regardless of its result.

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class StatusUpdateExample {
    public static void main(String[] args) {
        // Simulate an asynchronous task
        CompletableFuture<String> taskFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000); // Simulate task delay
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Task result";
        });

        // Update status when the task completes using thenRun
        taskFuture.thenRun(() -> System.out.println("Status updated: Task completed"));

        // Wait for the task to complete
        try {
            taskFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

Output:

Status updated: Task completed

Conclusion

The CompletableFuture.thenRun() method in Java is used for executing actions that should run after a CompletableFuture completes, regardless of the result. It is particularly useful in scenarios where you need to perform non-dependent follow-up tasks, such as logging completion, performing cleanup operations, or updating statuses.

Comments