Asynchronous Programming vs Multithreading
Asynchronous Programming vs Multithreading
Asynchronous Programming
Asynchronous programming is a programming paradigm that allows tasks to be executed
independently without blocking the main thread. It focuses on managing the flow of the
program by handling tasks concurrently and efficiently. It's commonly used to improve
the responsiveness of applications by avoiding long-running operations that might
otherwise cause the user interface to freeze. Java provides several mechanisms for
asynchronous programming, and in this tutorial, we'll cover the basics using -
Threads, CompletableFuture and the ExecutorService.
1. Threads
We can create a new thread to perform any operation asynchronously. With the release
of lambda expressions in Java 8, it’s cleaner and more readable.
Let’s create a new thread that computes and prints the factorial of a number:
try{
Thread.sleep(2000);
}
catch(InterruptedException e){
e.printStackTrace();
}
int ans=1;
for(int i=1;i<n;i++){
ans = ans*i;
}
System.out.println(Thread.currentThread().getName() + "is finished");
return ans;
}
int number = 5;
Thread newThread = new Thread(()->{
System.out.println("Factorial of 5 " + factorial(number));
});
newThread.start();
System.out.println("Main is still running-1");
}
}
2. FutureTask
Since Java 5, the Future interface provides a way to perform asynchronous operations
using the FutureTask. We can use the submit method of the ExecutorService to perform
the task asynchronously and return the instance of the FutureTask.
while (!futureTask.isDone()) {
System.out.println("FutureTask is not finished yet...");
}
long result = futureTask.get(); //Blocking Code
threadpool.shutdown();
Here we’ve used the isDone method provided by the Future interface to check if the
task is completed. Once finished, we can retrieve the result using the get method.
3. CompletableFuture
CompletableFuture is a class introduced in Java 8 that provides a way to perform
asynchronous operations and handle their results using a fluent API. Java 8 introduced
CompletableFuture with a combination of a Future and CompletionStage. It provides
various methods like supplyAsync, runAsync, and thenApplyAsync for asynchronous
programming.
Example-1
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
Example-2
Multi-threading
Multithreading involves the concurrent execution of two or more threads to achieve
parallelism. It is a fundamental concept for optimizing CPU-bound tasks and improving
overall system performance. Key Components for achieving multithreading in Java are
thread class and Executor Framework.
Thread Class: Java provides the Thread class for creating and managing threads.
Executor Framework: The ExecutorService and related interfaces offer a higher-
level abstraction for managing thread pools.
Summary
Asynchronous Programming:
Focuses on non-blocking execution.
Primarily used for IO-bound tasks and maintaining responsive applications.
Utilizes higher-level abstractions like CompletableFuture.
Emphasizes composability and chaining of asynchronous operations.
Multithreading:
Focuses on parallelism for CPU-bound tasks.
Suitable for tasks that can be executed concurrently.
Utilizes threads and thread pools, managed by the Thread class and
ExecutorService.
Requires attention to synchronization and shared state management.