You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何让回调函数在主线程中执行?

如何让回调函数在主线程执行

下面是几种针对你的测试代码的修改方案,都能实现回调在主线程运行的需求:

方案1:主线程维护任务队列,轮询处理回调

核心思路是让异步任务只负责把回调任务提交到线程安全的队列,主线程在等待期间主动从队列取出任务并执行,这样回调就会在主线程上下文运行。

修改后的完整代码:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.junit.Test;

@Test
void threadTest() throws InterruptedException {
    System.out.println("main thread:" + Thread.currentThread());
    BlockingQueue<Runnable> callbackQueue = new LinkedBlockingQueue<>();

    new Thread(new AsyncTask(() -> callbackQueue.put(this::callback))).start();

    // 主线程等待异步任务完成后,处理队列中的回调
    Thread.sleep(1100);
    Runnable callbackTask;
    while ((callbackTask = callbackQueue.poll()) != null) {
        callbackTask.run();
    }
}

private void callback() {
    System.out.println("callback executed in: " + Thread.currentThread());
}

static class AsyncTask implements Runnable {
    private final Runnable runnable;

    public AsyncTask(Runnable runnable) {
        this.runnable = runnable;
    }

    @Override
    public void run() {
        System.out.println("other thread: " + Thread.currentThread());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        this.runnable.run();
    }
}

方案2:用CountDownLatch同步,主线程触发回调

通过CountDownLatch让异步任务完成后发出信号,主线程收到信号后直接执行回调,这种方式逻辑简单,适合单个回调的场景。

修改后的代码:

import java.util.concurrent.CountDownLatch;
import org.junit.Test;

@Test
void threadTest() throws InterruptedException {
    System.out.println("main thread:" + Thread.currentThread());
    CountDownLatch latch = new CountDownLatch(1);

    new Thread(new AsyncTask(latch)).start();

    // 主线程阻塞等待异步任务完成
    latch.await();
    // 回调在主线程执行
    callback();
}

private void callback() {
    System.out.println("callback executed in: " + Thread.currentThread());
}

static class AsyncTask implements Runnable {
    private final CountDownLatch latch;

    public AsyncTask(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void run() {
        System.out.println("other thread: " + Thread.currentThread());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 异步任务完成,释放latch
        latch.countDown();
    }
}

方案3:利用CompletableFuture(Java 8+)

借助Java 8引入的CompletableFuture异步工具类,让主线程等待异步任务完成后执行回调,代码更简洁现代。

修改后的代码:

import java.util.concurrent.CompletableFuture;
import org.junit.Test;

@Test
void threadTest() throws InterruptedException {
    System.out.println("main thread:" + Thread.currentThread());

    CompletableFuture<Void> asyncTask = CompletableFuture.runAsync(() -> {
        System.out.println("other thread: " + Thread.currentThread());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    });

    // 等待异步任务结束,主线程执行回调
    asyncTask.join();
    callback();
}

private void callback() {
    System.out.println("callback executed in: " + Thread.currentThread());
}

各方案适用场景

  • 方案1:适合需要处理多个异步回调任务的场景,主线程可以持续轮询队列处理任务;
  • 方案2:适合单个回调的简单场景,代码逻辑直观易懂;
  • 方案3:适合Java 8及以上版本的项目,利用原生异步API简化代码。

内容的提问来源于stack exchange,提问作者PeMa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:36:18