Master AsyncTask Orchestration in Spring Boot with asyncTool
This guide explains how to integrate asyncTool into a Spring Boot project, configure custom thread pools, understand core interfaces like IWorker and ICallback, and implement serial, parallel, and mixed task flows with detailed code examples and best‑practice considerations.
Integration into Spring Boot
Add the asyncTool dependency to pom.xml:
<dependency>
<groupId>com.jd.platform</groupId>
<artifactId>asyncTool</artifactId>
<version>YOUR_VERSION</version>
</dependency>Configure a thread pool. Although asyncTool manages a pool internally, you can define a custom one for finer control. Two approaches are shown:
1) Custom Thread Pool
@Configuration
@EnableAsync // enable async execution
public class TaskExecutePool {
@Autowired
private TaskThreadPoolConfig config;
@Bean
public Executor myTaskAsyncPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(config.getCorePoolSize()); // core size
executor.setMaxPoolSize(config.getMaxPoolSize()); // max size
executor.setQueueCapacity(config.getQueueCapacity()); // queue capacity
executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); // keep‑alive
executor.setThreadNamePrefix("MyExecutor-"); // name prefix
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // rejection policy
executor.initialize();
return executor;
}
}2) Override Spring's Native Async Pool
@Configuration
@EnableAsync
public class NativeAsyncTaskExecutePool implements AsyncConfigurer {
@Autowired
private TaskThreadPoolConfig config;
@Bean
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(config.getCorePoolSize());
executor.setMaxPoolSize(config.getMaxPoolSize());
executor.setQueueCapacity(config.getQueueCapacity());
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
executor.setThreadNamePrefix("MyExecutor2-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, objects) -> {
log.error("==========================" + ex.getMessage() + "=======================", ex);
log.error("exception method:" + method.getName());
};
}
}Core API Overview
IWorker Interface
action(T object, Map<String, WorkerWrapper> allWrappers): Executes the task logic. object is the input, allWrappers provides access to other tasks' results. defaultValue(): Value returned when the task times out or throws an exception.
ICallback Interface
begin(): Called when the task starts.
result(boolean success, T param, WorkResult<V> workResult): Called after execution; success indicates outcome, param is the input, and workResult holds the result.
WorkerWrapper Class
id: Unique identifier of the task. param: Input parameter. worker: Concrete implementation of IWorker. callback: Implementation of ICallback. depend: Declares strong dependencies that enforce execution order. next: Declares subsequent tasks for flexible sequencing.
Detailed Usage and Examples
1. Serial Tasks
Tasks are executed one after another in the defined order.
// Task A
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerA")
.worker(new WorkerA())
.callback(new WorkerA())
.param(1)
.build();
// Task B depends on A
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerB")
.worker(new WorkerB())
.callback(new WorkerB())
.param(2)
.depend(wrapperA)
.build();
// Task C depends on B
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerC")
.worker(new WorkerC())
.callback(new WorkerC())
.param(3)
.depend(wrapperB)
.build();
Async.beginWork(1000, wrapperA);2. Parallel Tasks
Multiple tasks run concurrently.
// Define three independent tasks
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()…build();
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()…build();
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()…build();
Async.beginWork(1000, wrapperA, wrapperB, wrapperC);3. Block‑Wait: Serial then Parallel
Execute A first, then run B and C in parallel.
// A
WorkerWrapper wrapperA = …build();
// B depends on A
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()
.depend(wrapperA)
.build();
// C depends on A
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()
.depend(wrapperA)
.build();
Async.beginWork(1000, wrapperA);4. Block‑Wait: Parallel then Serial
B and C run together; after they finish, A runs.
// A will receive results of B and C
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()
.param(null)
.build();
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()
.next(wrapperA)
.build();
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()
.next(wrapperA)
.build();
Async.beginWork(1000, wrapperB, wrapperC);Key Benefits
1. Task Orchestration
asyncTool enables flexible combinations of parallel and serial execution, allowing developers to model complex business workflows.
2. Dependency Management
Both strong and weak dependencies can be expressed, ensuring correct ordering while permitting concurrent execution where possible.
3. Monitoring & Callbacks
Every task triggers callbacks for success, failure, timeout, or being skipped, giving real‑time visibility into the execution chain.
4. Exception Handling & Fault Tolerance
Tasks can define timeout thresholds and default return values; isolated failures do not cascade unless upstream dependencies also fail.
5. Performance Optimizations
Low‑thread design reuses threads across dependent tasks, and the framework operates without locks, reducing contention and improving throughput.
6. Result Management
Results can be returned in the order tasks were added, and the whole task group supports asynchronous callbacks to avoid blocking the main thread.
7. Thread‑Pool Flexibility
Each task group may have a dedicated pool or share a common pool, giving fine‑grained resource control.
8. Simplified Development
Complex concurrency logic is encapsulated, letting developers focus on business code rather than low‑level thread handling.
Precautions
Thread Safety : Ensure that task implementations are safe for concurrent execution.
Exception Handling : Properly catch and handle exceptions inside tasks to prevent unexpected termination.
Timeout Configuration : Set reasonable timeouts to avoid resource waste.
Dependency Configuration : Accurately define dependencies to achieve the intended execution order.
By following the steps and guidelines above, you can effectively use asyncTool in a Spring Boot application to orchestrate complex multi‑threaded workflows.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
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.
