Asynchronous Execution Techniques in Spring Boot with CompletableFuture
The article explains multiple methods for implementing asynchronous execution in Spring Boot, covering @Async annotation, Java 8 CompletableFuture, Callable, WebAsyncTask, DeferredResult, Tomcat connection tuning, container switching to Undertow, and async interception, all illustrated with complete code examples.
This article introduces several ways to achieve asynchronous execution in Spring Boot, including using the @Async annotation with @EnableAsync and leveraging Java 8's CompletableFuture API.
Example 1 shows a custom thread class AskThread that waits for a CompletableFuture result; the main method creates the future, starts a new thread, simulates a long computation with Thread.sleep, and completes the future with a value.
<pre><code>@AllArgsConstructor
public class AskThread implements Runnable {
private CompletableFuture<Integer> re = null;
public void run() {
int myRe = 0;
try {
myRe = re.get() * re.get();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(myRe);
}
public static void main(String[] args) throws InterruptedException {
final CompletableFuture<Integer> future = new CompletableFuture<>();
new Thread(new AskThread(future)).start();
// simulate long computation
Thread.sleep(1000);
// complete result
future.complete(60);
}
}</code></pre>Example 2 demonstrates a static method calc that sleeps to simulate a long‑running task and returns the square of the input, then uses CompletableFuture.supplyAsync to execute it asynchronously, converting the result to a string and printing it.
<pre><code>public class Calc {
public static Integer calc(Integer para) {
try {
// simulate long execution
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return para * para;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
final CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> calc(50))
.thenApply(i -> Integer.toString(i))
.thenApply(str -> "\"" + str + "\"")
.thenAccept(System.out::println);
future.get();
}
}</code></pre>The article also covers other asynchronous techniques such as using Callable in a controller, WebAsyncTask with timeout handling, and DeferredResult with callbacks for completion and timeout.
<pre><code>@RestController
public class HelloController {
@Autowired
private HelloService hello;
@GetMapping("/hello")
public Callable<String> helloController() {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
return hello.sayHello();
}
};
return callable;
}
@GetMapping("/world")
public WebAsyncTask<String> worldController() {
WebAsyncTask<String> task = new WebAsyncTask<>(3000, () -> hello.sayHello());
task.onTimeout(() -> { throw new TimeoutException("调用超时"); });
return task;
}
@GetMapping("/deferred")
public DeferredResult<String> executeSlowTask() {
DeferredResult<String> result = new DeferredResult<>();
// long‑running task sets result later
return result;
}
}</code></pre>Configuration tips are provided for increasing the embedded Tomcat connector's maximum connections and threads, and for switching the default servlet container to Undertow.
<pre><code>@Configuration
public class TomcatConfig {
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers(new MyTomcatConnectorCustomizer());
factory.setPort(8005);
factory.setContextPath("/api-g");
return factory;
}
class MyTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
@Override
public void customize(Connector connector) {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setMaxConnections(20000);
protocol.setMaxThreads(2000);
protocol.setConnectionTimeout(30000);
}
}
}</code></pre>It also shows how to replace Tomcat with Undertow by excluding the Tomcat starter and adding the Undertow starter dependency.
<pre><code><exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency></code></pre>Finally, an AsyncHandlerInterceptor implementation demonstrates how to intercept asynchronous requests, modify the response, and handle exceptions.
<pre><code>@Component
public class MyAsyncHandlerInterceptor implements AsyncHandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(MyAsyncHandlerInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
logger.info(Thread.currentThread().getName() + "服务调用完成,返回结果给客户端");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (ex != null) {
System.out.println("发生异常:" + ex.getMessage());
}
}
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String resp = "my name is chhliu!";
response.setContentLength(resp.length());
response.getOutputStream().write(resp.getBytes());
logger.info(Thread.currentThread().getName() + "进入afterConcurrentHandlingStarted方法");
}
}</code></pre>Overall, the guide provides practical code examples and configuration advice for improving concurrency, performance, and scalability in Spring Boot backend applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
