Backend Development 11 min read

Eight Ways to Implement Asynchronous Programming in Java

This article introduces eight common Java asynchronous implementation techniques—including raw threads, thread pools, Future, CompletableFuture, Spring @Async, ApplicationEvent, message queues, ThreadUtil, and Guava ListenableFuture—explains their use cases, advantages, and limitations, and provides concrete code examples for each method.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Eight Ways to Implement Asynchronous Programming in Java

Asynchronous execution is essential for reducing latency in scenarios such as sending SMS, emails, or updating data. The article first explains why asynchronous processing is beneficial compared to synchronous execution, using a typical order‑placement flow as an example.

It then enumerates eight practical ways to achieve asynchrony in Java:

Direct Thread subclassing.

Using Future with an ExecutorService .

Leveraging the CompletableFuture API.

Applying Spring's @Async annotation.

Publishing and handling ApplicationEvent events.

Integrating message queues (e.g., RabbitMQ).

Utilizing Hutool's ThreadUtil utility.

Employing Guava's ListenableFuture .

Thread example: A simple AsyncThread class extends Thread and prints a message in its run method. The article notes that creating a thread per task is inefficient and suggests using a thread pool:

private ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(() -> log.info("执行业务逻辑..."));

Future example: Demonstrates submitting a Callable to a fixed‑size pool and retrieving the result with future.get() , while also discussing Future's drawbacks such as lack of callbacks and poor error handling.

CompletableFuture example: Shows chaining tasks with thenRunAsync and retrieving results without explicitly managing an ExecutorService , as it uses the internal ForkJoinPool by default.

Spring @Async: Provides a custom thread‑pool configuration bean named taskExecutor and illustrates asynchronous service methods annotated with @Async("taskExecutor") for sending SMS and email.

ApplicationEvent: Defines an AsyncSendEmailEvent class extending ApplicationEvent and an event listener implementing ApplicationListener<AsyncSendEmailEvent> , both annotated with @Async to process the event asynchronously.

Message Queue: Presents a producer that sends delayed messages using AmqpTemplate and a consumer that manually acknowledges or nacks messages based on processing outcome.

ThreadUtil: Uses Hutool's ThreadUtil.execAsync to run simple tasks in parallel, demonstrating quick thread‑local random number generation.

Guava ListenableFuture: Creates a ListeningExecutorService via MoreExecutors.listeningDecorator , submits a Callable , and attaches success/failure callbacks with Futures.addCallback , avoiding the need for explicit get() polling.

The article concludes by encouraging readers to discuss and share their thoughts on these asynchronous techniques.

backendJavaSpringAsynchronousCompletableFutureMessageQueue
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.