Using Asynchronous Threads in Spring Boot: @Async, AsyncManager, and ThreadPoolExecutor

This article explains how to implement asynchronous processing in Java Spring Boot using the @Async annotation, the built‑in AsyncManager, and a custom ThreadPoolExecutor, providing code examples, configuration steps, and best‑practice tips for managing background tasks without blocking the main thread.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Using Asynchronous Threads in Spring Boot: @Async, AsyncManager, and ThreadPoolExecutor

Overall Description

In Java, asynchronous threads are important for time‑consuming operations such as notifying hardware, sending SMS, or uploading images, because handling them in the main thread would block the business flow; using async threads keeps the main thread free.

Recent project experience with many thread operations is recorded here.

Implementation Methods

There are several common ways to work with threads in Spring Boot: the @Async annotation, the built‑in AsyncManager, and a custom thread pool.

1. @Async Annotation

The @Async annotation cannot be called directly on the class itself; it should be placed on a method in a separate @Service and invoked from another component.

1. Add @EnableAsync

Enable async support in a configuration class:

package com.thcb.boot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * MyConfig
 *
 * @author thcb
 */
@Configuration
@EnableAsync
public class MyConfig {
    // custom config
}

2. Create an async service

Define an interface with an @Async method and its implementation:

package com.thcb.execute.service;

import org.springframework.scheduling.annotation.Async;

public interface IExecuteService {
    /**
     * Simulated time‑consuming operation
     */
    @Async
    void sleepingTest();
}
package com.thcb.execute.service.impl;

import com.thcb.execute.service.IExecuteService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public class ExecuteServiceImpl implements IExecuteService {
    private static final Logger log = LoggerFactory.getLogger(ExecuteServiceImpl.class);

    @Override
    public void sleepingTest() {
        log.info("SleepingTest start");
        try {
            Thread.sleep(5000);
        } catch (Exception e) {
            log.error("SleepingTest:" + e);
        }
        log.info("SleepingTest end");
    }
}

2. AsyncManager

AsyncManager is a Spring‑Boot task manager that can schedule TimerTask instances.

1. Create AsyncManager class

public class AsyncManager {
    /** operation delay 10 ms */
    private final int OPERATE_DELAY_TIME = 10;

    /** thread pool */
    private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");

    /** singleton */
    private AsyncManager() {}
    private static final AsyncManager me = new AsyncManager();
    public static AsyncManager me() { return me; }

    /** execute task */
    public void execute(TimerTask task) {
        executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }

    /** shutdown */
    public void shutdown() {
        Threads.shutdownAndAwaitTermination(executor);
    }
}

2. Create a time‑consuming TimerTask

public TimerTask sleepingTest() {
    return new TimerTask() {
        @Override
        public void run() {
            // time‑consuming operation
            try {
                Thread.sleep(5000);
            } catch (Exception e) {
                log.error("SleepingTest:" + e);
            }
        }
    };
}

3. Execute with AsyncManager

// async thread pool
AsyncManager.me().execute(sleepingTest());

3. ThreadPoolExecutor

A custom thread pool with a rejection policy allows fine‑grained control over core size, max size, queue length and keep‑alive time.

1. Create thread pool

private static final ThreadPoolExecutor threadPoolExecutor =
    new ThreadPoolExecutor(5, 10, 30, TimeUnit.SECONDS,
        new LinkedBlockingQueue<Runnable>(20),
        new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                log.error("Task rejected");
            }
        });

2. Define a Runnable task

static class MyTask implements Runnable {
    private int taskNum;
    public MyTask(int num) { this.taskNum = num; }

    @Override
    public void run() {
        System.out.println("Executing task " + taskNum);
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("task " + taskNum + " completed");
    }
}

3. Submit tasks

for (int i = 0; i < 20; i++) {
    MyTask myTask = new MyTask(i);
    threadPoolExecutor.execute(myTask);
    System.out.println("Pool size: " + threadPoolExecutor.getPoolSize()
        + ", queue size: " + threadPoolExecutor.getQueue().size()
        + ", completed: " + threadPoolExecutor.getCompletedTaskCount());
}
threadPoolExecutor.shutdown();

Summary

Thread count should match CPU cores; always release threads to avoid exhaustion.

@Async methods must be placed in a separate @Service because Spring creates a proxy.

Define a single static final thread pool and reuse it instead of creating new instances each time.

Java 8 also introduced CompletableFuture, which can be covered in a separate article.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentThreadPoolAsynchronousSpring BootAsync
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

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.