java代码我这样的场景如何异步转同步?

控制器方法被调用后,发了一条消息到MQ,MQ消费后写入redis处理结果。
现在想要在控制器方法被调用后返回处理结果,目前的做法是死循环轮询判断redis有无结果,感觉好傻,有没有其他优雅的方案。

阅读 2.3k
avatarAI BotBETA

在这个场景中,要实现从异步到同步的转换,一种可能的解决方案是使用Java的CompletableFutureCompletableFuture是Java 8引入的一个功能,它允许你以非阻塞的方式编写异步代码,并提供了优雅的方法来处理异步操作的结果。

下面是一个示例代码,展示了如何使用CompletableFuture来异步发送消息到MQ,并在接收到处理结果后同步返回:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class AsyncToSyncExample {
    // 假设有一个方法用于向MQ发送消息并返回一个CompletableFuture
    public static CompletableFuture<String> sendMessageToMQ(String message) {
        // 模拟异步发送消息到MQ
        return CompletableFuture.supplyAsync(() -> {
            // 模拟处理时间
            try {
                Thread.sleep(3000); // 假设处理需要3秒钟
            } catch (InterruptedException e) {
                throw new RuntimeException("Interrupted while processing message", e);
            }
            // 模拟处理结果
            return "Processed result: " + message;
        });
    }

    // 控制器方法,异步发送消息并同步返回处理结果
    public static String controllerMethod(String inputMessage) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = sendMessageToMQ(inputMessage);
        // 使用CompletableFuture的get方法阻塞等待结果
        return future.get();
    }

    public static void main(String[] args) throws Exception {
        String result = controllerMethod("Hello MQ");
        System.out.println("Result: " + result);
    }
}

在上面的示例中,sendMessageToMQ方法模拟了异步发送消息到MQ的操作,并返回一个CompletableFuturecontrollerMethod方法在调用sendMessageToMQ后,通过调用CompletableFutureget方法来阻塞等待结果。这种方式可以实现从异步到同步的转换,同时避免了轮询Redis的笨拙做法。

4 个回答

首先我觉得轮询也并不是不能接受的方案,很多时候外部程序就是没办法回调,这种情况下轮询也没什么不好。
然后来到你这个场景,我理解你应该是想优雅地实现一个异步过程的回调。我猜你现在的做法是控制器发消息到MQ后,控制器的线程持续轮询redis看是否有结果,直到有结果或超时才返回。这种情况下,可以考虑让当前线程阻塞,通过消费者的行为通知到本地,比如使用redis的pub/sub,或者消费者写一个处理完成的消息到MQ,再由消费到这个消息的线程唤起阻塞线程。
我之前做过一个异步过程是本地程序另起一个http接口用来接收完成消息,控制器启动异步过程后让线程阻塞在一个对象上,异步过程结束的最后会通过这个额外的接口接收成功消息。等另起的接口收到请求后,找到之前用来阻塞的那个对象,唤醒阻塞在对象上的线程即可。

1.单任务处理

 CompletableFuture.supplyAsync(() -> {
        // 处理逻辑结果返回给局部变量(集合)
 }}, threadPool).whenComplete((v, e) -> {
        // 执行完成返回局部变量(集合)结果
 }

2.多任务处理

1.CompletableFuture<?>[] futures = list的处理结果

// 阻塞list结果返回
2.CompletableFuture.allOf(futures).join(); 
新手上路,请多包涵

优雅点,有时间可以搞一个简单的webSocket,MQ异步消费成功写入rerdis后,直接发送推送结果给前端

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏