Backend Development 9 min read

How to Orchestrate Parallel and Dependent Tasks with AsyncTool

This article introduces AsyncTool, a Java concurrency framework that enables flexible parallel, serial, dependent, and callback‑driven task orchestration, explains its core components (worker, callback, wrapper), and provides multiple code‑first examples illustrating complex workflow compositions.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Orchestrate Parallel and Dependent Tasks with AsyncTool

Environment: asyncTool 1.4‑SNAPSHOT + JDK 1.8.

Overview

AsyncTool is a concurrency framework that can handle arbitrary parallel, serial, blocking, dependent, and callback‑driven workflows. It allows free composition of thread execution order with full‑link callbacks and timeout control.

Typical Parallel Scenarios

Client request triggers N micro‑service calls.

Execute N tasks in parallel, then decide the next step based on their results.

Batch tasks that require thread isolation.

Single‑machine workflow orchestration.

Other ordered orchestration needs.

Task‑Orchestration Use Cases

Serial requests of multiple execution units.

Parallel requests of multiple execution units.

Blocking wait where a serial step is followed by several parallel steps.

Blocking wait where several parallel steps must finish before a subsequent step.

Interleaved serial‑parallel dependencies.

Core Building Blocks

worker : the smallest execution unit, usually a network call or a time‑consuming operation.

<code>public interface IWorker<T, V> {
    V action(T object, Map<String, WorkerWrapper> allWrappers);
    V defaultValue();
}</code>

callback : invoked after a worker finishes, providing success flag, original parameters and detailed results.

<code>public interface ICallback<T, V> {
    void begin();
    void result(boolean success, T param, WorkResult<V> workResult);
}</code>

wrapper : combines a worker and its callback into the smallest scheduling unit; linking wrappers defines execution order.

Usage Example

Define basic tasks

<code>static class Task1 implements IWorker<String, String>, ICallback<String, String> {
    @Override
    public String action(String object, Map<String, WorkerWrapper> allWrappers) {
        try { TimeUnit.SECONDS.sleep(1); System.out.println("任务1,执行完成"); } catch (InterruptedException e) {}
        return "Task1 - Complete";
    }
    @Override public String defaultValue() { return "Task1 - defaultValue"; }
    @Override public void begin() { System.out.println("Task1 - begin"); }
    @Override public void result(boolean success, String param, WorkResult<String> workResult) {
        if (success) { System.out.println("Task1 执行结果:" + workResult.getResult()); }
    }
}
// Task2 and Task3 are similar, sleeping 2 and 3 seconds respectively.
</code>

Case 1: Parallel execution of three tasks

<code>Task1 w1 = new Task1();
Task2 w2 = new Task2();
Task3 w3 = new Task3();

WorkerWrapper<String, String> wrapper1 = new WorkerWrapper.Builder<String, String>()
    .worker(w1).callback(w1).build();
WorkerWrapper<String, String> wrapper2 = new WorkerWrapper.Builder<String, String>()
    .worker(w2).callback(w2).build();
WorkerWrapper<String, String> wrapper3 = new WorkerWrapper.Builder<String, String>()
    .worker(w3).callback(w3).build();

long now = SystemClock.now();
System.out.println("begin-" + now);
Async.beginWork(6100, wrapper1, wrapper2, wrapper3);
System.out.println("end-" + SystemClock.now());
System.err.println("cost-" + (SystemClock.now() - now));
Async.shutDown();
</code>

Output shows each task beginning, completing, and the total cost.

Case 2: Two tasks run together, then a third after they finish

<code>// Build wrappers, set next relationship for task3 after task1
WorkerWrapper<String, String> wrapper3 = new WorkerWrapper.Builder<String, String>()
    .worker(w3).callback(w3).build();
WorkerWrapper<String, String> wrapper1 = new WorkerWrapper.Builder<String, String>()
    .worker(w1).callback(w1).next(wrapper3).build();
WorkerWrapper<String, String> wrapper2 = new WorkerWrapper.Builder<String, String>()
    .worker(w2).callback(w2).build();

Async.beginWork(10000, wrapper1, wrapper2);
</code>

Similar output demonstrates the ordering.

Case 3 and Case 4 illustrate dependent and chained executions using .depend() and .next() to build more complex graphs.

Overall, AsyncTool supports arbitrary task composition, allowing developers to model complex parallel‑serial workflows with concise Java code.

JavaconcurrencyAsynctask orchestrationcallbackParallel Execution
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

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.