控制器方法被调用后,发了一条消息到MQ,MQ消费后写入redis处理结果。
现在想要在控制器方法被调用后返回处理结果,目前的做法是死循环轮询判断redis有无结果,感觉好傻,有没有其他优雅的方案。
控制器方法被调用后,发了一条消息到MQ,MQ消费后写入redis处理结果。
现在想要在控制器方法被调用后返回处理结果,目前的做法是死循环轮询判断redis有无结果,感觉好傻,有没有其他优雅的方案。
在这个场景中,要实现从异步到同步的转换,一种可能的解决方案是使用Java的CompletableFuture
。CompletableFuture
是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的操作,并返回一个CompletableFuture
。controllerMethod
方法在调用sendMessageToMQ
后,通过调用CompletableFuture
的get
方法来阻塞等待结果。这种方式可以实现从异步到同步的转换,同时避免了轮询Redis的笨拙做法。
1.单任务处理
CompletableFuture.supplyAsync(() -> {
// 处理逻辑结果返回给局部变量(集合)
}}, threadPool).whenComplete((v, e) -> {
// 执行完成返回局部变量(集合)结果
}
2.多任务处理
1.CompletableFuture<?>[] futures = list的处理结果
// 阻塞list结果返回
2.CompletableFuture.allOf(futures).join();
3 回答2.8k 阅读✓ 已解决
3 回答4.3k 阅读✓ 已解决
2 回答2.9k 阅读✓ 已解决
8 回答3.9k 阅读
3 回答2.7k 阅读✓ 已解决
4 回答2.1k 阅读
2 回答2.2k 阅读✓ 已解决
首先我觉得轮询也并不是不能接受的方案,很多时候外部程序就是没办法回调,这种情况下轮询也没什么不好。
然后来到你这个场景,我理解你应该是想优雅地实现一个异步过程的回调。我猜你现在的做法是控制器发消息到MQ后,控制器的线程持续轮询redis看是否有结果,直到有结果或超时才返回。这种情况下,可以考虑让当前线程阻塞,通过消费者的行为通知到本地,比如使用redis的pub/sub,或者消费者写一个处理完成的消息到MQ,再由消费到这个消息的线程唤起阻塞线程。
我之前做过一个异步过程是本地程序另起一个http接口用来接收完成消息,控制器启动异步过程后让线程阻塞在一个对象上,异步过程结束的最后会通过这个额外的接口接收成功消息。等另起的接口收到请求后,找到之前用来阻塞的那个对象,唤醒阻塞在对象上的线程即可。