Elegant Orchestration and Efficient Execution of Complex Tasks with Spring asyncTool
This guide shows how to integrate asyncTool into a Spring Boot project, configure custom thread pools, define core interfaces, and compose serial, parallel, or mixed task flows with full‑link callbacks, fault tolerance, and performance optimizations for complex multi‑threaded orchestration.
Integration into Spring Boot
1. Add dependency
Add the asyncTool dependency to the pom.xml file:
<dependency>
<groupId>com.jd.platform</groupId>
<artifactId>asyncTool</artifactId>
<version>YOUR_VERSION</version>
</dependency>2. Configure thread pool
asyncTool manages an internal pool, but a custom pool can be supplied. Two configuration approaches are provided.
Custom thread pool
@Configuration
@EnableAsync
public class TaskExecutePool {
@Autowired
private TaskThreadPoolConfig config;
@Bean
public Executor myTaskAsyncPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(config.getCorePoolSize());
executor.setMaxPoolSize(config.getMaxPoolSize());
executor.setQueueCapacity(config.getQueueCapacity());
executor.setKeepAliveSeconds(config.getKeepAliveSeconds());
executor.setThreadNamePrefix("MyExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}Override native Spring 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
IWorker interface
action(T object, Map<String, WorkerWrapper> allWrappers): task logic; object is the input, allWrappers provides results of other tasks. defaultValue(): value returned when the task times out or throws an exception.
ICallback interface
begin(): invoked when the task starts.
result(boolean success, T param, WorkResult<V> workResult): invoked with the execution outcome.
WorkerWrapper class
id: unique identifier of the task. param: input parameter for the task. worker: concrete implementation of the task. callback: callback implementation. depend: strong dependency (must finish before this task runs). next: subsequent task used to define execution order.
Usage examples
Serial tasks
// Define task A
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerA")
.worker(new WorkerA())
.callback(new WorkerA())
.param(1)
.build();
// Define task B, dependent on A
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerB")
.worker(new WorkerB())
.callback(new WorkerB())
.param(2)
.depend(wrapperA)
.build();
// Define task C, dependent on B
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerC")
.worker(new WorkerC())
.callback(new WorkerC())
.param(3)
.depend(wrapperB)
.build();
// Submit tasks (only the first task needs to be submitted; dependencies are resolved internally)
Async.beginWork(1000, wrapperA);Parallel tasks
// Define tasks A, B, C without dependencies
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()...build();
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()...build();
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()...build();
// Submit all at once
Async.beginWork(1000, wrapperA, wrapperB, wrapperC);Mixed: serial then parallel
// A runs first, then B and C run in parallel
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()...build();
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()...depend(wrapperA)...build();
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()...depend(wrapperA)...build();
Async.beginWork(1000, wrapperA);Mixed: parallel then serial
// B and C run in parallel, after they finish A runs
WorkerWrapper wrapperA = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerA")
.worker(new WorkerA())
.callback(new WorkerA())
.param(null) // will receive results of B and C
.build();
WorkerWrapper wrapperB = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerB")
.worker(new WorkerB())
.callback(new WorkerB())
.param(2)
.next(wrapperA)
.build();
WorkerWrapper wrapperC = new WorkerWrapper.Builder<Integer, Integer>()
.id("workerC")
.worker(new WorkerC())
.callback(new WorkerC())
.param(3)
.next(wrapperA)
.build();
Async.beginWork(1000, wrapperB, wrapperC);Main capabilities
Task orchestration : flexible combination of parallel and serial tasks, allowing developers to define execution order according to business needs.
Dependency management : supports strong and weak dependencies; a task can wait for one or many upstream tasks before executing.
Execution monitoring and callbacks : every task triggers callbacks for start, success, failure, timeout, or being skipped, enabling real‑time monitoring.
Exception handling and fault tolerance : each task can specify a timeout and a default return value; failures of independent tasks do not affect others, while dependent tasks inherit failure status.
Performance optimization : low‑thread design reduces thread creation overhead; the framework is lock‑free and can reuse threads across dependent tasks.
Result management : results can be returned in the order tasks were added or via asynchronous callbacks, avoiding blocking the main thread.
Thread‑pool management : thread pools can be shared across task groups or dedicated per group, offering flexible resource allocation.
Simplified development : asyncTool encapsulates complex concurrency logic, letting developers focus on business logic without deep knowledge of low‑level threading.
Precautions
Thread safety : ensure that task implementations are safe for concurrent execution.
Exception handling : handle exceptions within tasks to prevent cascading failures.
Timeout settings : configure reasonable timeouts to avoid resource waste.
Dependency configuration : correctly set dependencies to achieve the intended execution sequence.
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.
IoT Full-Stack Technology
Dedicated to sharing IoT cloud services, embedded systems, and mobile client technology, with no spam ads.
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.
