Fundamentals 10 min read

Module Interaction: Synchronous, Asynchronous, and Callback Calls in Java

This article explains the three main ways modules can call each other—synchronous calls, asynchronous calls, and callbacks—illustrates each with Java code examples, and discusses when to use each approach for flexible and non‑blocking program design.

Java Captain
Java Captain
Java Captain
Module Interaction: Synchronous, Asynchronous, and Callback Calls in Java

In an application system, regardless of the programming language, modules inevitably call each other, and the invocation methods can be divided into three categories: synchronous calls, asynchronous calls, and callbacks.

Synchronous Call

A synchronous call is the most basic and straightforward method where method a() of class A invokes method b() of class B and waits until b() finishes before continuing. This approach is suitable only when b() executes quickly; otherwise it blocks the entire flow.

Asynchronous Call

An asynchronous call solves the blocking problem of synchronous calls. Class A starts a new thread to invoke class B’s method b() , allowing method a() to continue immediately. The result of b() must be listened for separately, for example using Future + Callable in Java.

Callback

A callback is a two‑way invocation where class A calls class B’s method, and after B finishes it actively calls back a method on A. This creates a bidirectional communication pattern.

Code Example

The following Java code demonstrates a callback scenario where a teacher asks a student a question, the student thinks for a while, and then reports the answer back to the teacher.

/**
 * Callback interface
 */
public interface Callback {
    void tellAnswer(int answer);
}
/**
 * Teacher object implementing Callback
 */
public class Teacher implements Callback {
    private Student student;
    public Teacher(Student student) {
        this.student = student;
    }
    public void askQuestion() {
        student.resolveQuestion(this);
    }
    @Override
    public void tellAnswer(int answer) {
        System.out.println("知道了,你的答案是" + answer);
    }
}
/**
 * Student interface
 */
public interface Student {
    void resolveQuestion(Callback callback);
}
/**
 * A concrete student named Ricky
 */
public class Ricky implements Student {
    @Override
    public void resolveQuestion(Callback callback) {
        // Simulate solving the problem
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // handle interruption
        }
        // Callback to tell the teacher the answer
        callback.tellAnswer(3);
    }
}
/**
 * Callback test
 */
public class CallbackTest {
    @Test
    public void testCallback() {
        Student student = new Ricky();
        Teacher teacher = new Teacher(student);
        teacher.askQuestion();
    }
}

Running the test prints a single line: 知道了,你的答案是3 .

The example demonstrates a bidirectional call: the teacher invokes resolveQuestion on the student, and the student, after solving the problem, invokes the teacher’s tellAnswer callback.

Analysis

Two levels of abstraction are shown: abstracting the teacher so that any student only needs to know the callback interface, and abstracting the student so that the teacher can work with multiple students (e.g., a list of Student instances). This illustrates the benefits of using interfaces for flexibility and extensibility.

The core idea of callbacks is that the caller passes this (or another reference) to the callee, allowing the callee to notify the caller with needed information after completion. Callbacks can be used synchronously or asynchronously, depending on whether the caller needs to wait for the result.

When multiple pieces of data need to be returned with different priorities, callbacks provide a clean way to separate and handle each piece without inflating return objects.

In scenarios where many students are asked simultaneously, asynchronous callbacks let each student report back independently, avoiding the need for the teacher to poll or wait sequentially.

design patternsJavaProgrammingasynchronouscallbacksynchronous
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.