Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the spectra-pro domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home4/mahidhar/public_html/wp-includes/functions.php on line 6114
Asynchronous Programming in Java | tutorialQ

Asynchronous Programming in Java

Introduction

Asynchronous programming is a form of parallel programming that allows a unit of work to run separately from the primary application thread. When the work is complete, it notifies the main thread or handles the result in a callback.

Futures and CompletableFutures

Future

The Future interface represents the result of an asynchronous computation. It provides methods to check if the computation is complete, to wait for its completion, and to retrieve the result.

Java
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class FutureExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Callable<Integer> task = () -> {
            Thread.sleep(1000);
            return 123;
        };

        Future<Integer> future = executor.submit(task);

        try {
            Integer result = future.get(); // Blocking call
            System.out.println("Result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}

CompletableFuture

CompletableFuture is a more flexible and powerful way to handle asynchronous computations. It allows you to attach callbacks to the future, handle exceptions, and compose multiple futures.

Java
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 123;
        });

        future.thenAccept(result -> System.out.println("Result: " + result));

        System.out.println("Main thread continues to run...");
        
        try {
            // Block and wait for the result to prevent the program from exiting immediately
            future.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Advanced Features

Combining CompletableFutures:
You can combine multiple CompletableFuture instances using methods like thenCombine, thenCompose, and allOf.

Java
import java.util.concurrent.CompletableFuture;

public class CombineCompletableFutures {
    public static void main(String[] args) {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 50);
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 70);

        CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, Integer::sum);
        combinedFuture.thenAccept(result -> System.out.println("Combined Result: " + result));

        try {
            // Block and wait for the result to prevent the program from exiting immediately
            combinedFuture.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Exception Handling

CompletableFuture provides methods to handle exceptions using handle, exceptionally, and whenComplete.

Java
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExceptionHandling {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("Something went wrong");
            }
            return 42;
        });

        future.exceptionally(ex -> {
            System.out.println("Exception: " + ex.getMessage());
            return 0;
        }).thenAccept(result -> System.out.println("Result: " + result));

        try {
            // Block and wait for the result to prevent the program from exiting immediately
            future.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Conclusion

Multi-threading and asynchronous programming are essential concepts in Java that help improve application performance and responsiveness. Understanding how to create and manage threads, synchronize resources, and utilize Future and CompletableFuture for asynchronous tasks is crucial for developing efficient Java applications. With these tools and techniques, you can write scalable, high-performance code that leverages the full power of modern multi-core processors.

Scroll to Top