Java 如何处理需要组合以创建响应的多个客户端请求?

Java 如何处理需要组合以创建响应的多个客户端请求?,java,jakarta-ee,jax-rs,thread-synchronization,Java,Jakarta Ee,Jax Rs,Thread Synchronization,我正在使用JAX-RS来处理客户机请求。场景是这样的:客户被分成5个组。每个客户机都需要向服务器提交一个号码,当属于同一组的所有5个客户机完成提交号码后,服务器将计算这些号码的总和,并将结果返回给所有客户机 因为当一个客户机提交一个数字时,他们必须等待其他客户机也这样做(如果他们不是最后一个),我使用的是异步响应API,它允许在不过载服务器的情况下等待其他客户机。假设没有超时限制 我对JAX-RS的内部工作原理、会话和上下文缺乏了解,这使得我很难设计出正确的解决方案。以下是我的想法(在混合代码伪

我正在使用JAX-RS来处理客户机请求。场景是这样的:客户被分成5个组。每个客户机都需要向服务器提交一个号码,当属于同一组的所有5个客户机完成提交号码后,服务器将计算这些号码的总和,并将结果返回给所有客户机

因为当一个客户机提交一个数字时,他们必须等待其他客户机也这样做(如果他们不是最后一个),我使用的是异步响应API,它允许在不过载服务器的情况下等待其他客户机。假设没有超时限制

我对JAX-RS的内部工作原理、会话和上下文缺乏了解,这使得我很难设计出正确的解决方案。以下是我的想法(在混合代码伪代码中):

公共类汇总资源{
@注入
SummationService;//与实体管理器对话
//集团客户编号
静态地图组地图;
@职位
@路径(“{clientId}”)
公共无效提交(int num,
@PathParam(“clientId”)长clientId,
@挂起的异步响应){
新线程(){
@凌驾
公开募捐{
long groupId=service.getGroupOfClient(clientId);
Map clients=groupMap.get(groupId);
clients.put(clientId,num);
如果(clients.size()!=5)
//等待(见以下要点)
其他的
//释放此组的所有线程
int sum=HelperClass.sum(clients.values());//只应执行一次
回复:简历(金额);
}
}.start();
}
}
我想谈的几点:

  • 我知道我可以将其存储在数据库中而不是内存中,但假设客户端之间的提交时间很短,从数据库中写入和读取数据的成本更高。
    groupMap
    对于每个submit调用(由不同的客户端)是否不同?使其静态化是否足以在所有实例中共享
  • 为了同步线程,我可以制作一个
    映射锁
    ,它将一个groupID映射到一个同步锁对象。因此,每个线程都通过调用locks.get(groupId).wait()进行等待,释放行是
    locks.get(groupId).notifyAll()
    。锁对象由属于组的第一个线程创建。我不知道这种方法是否对JAX-RS和异步响应友好。Wait notify在今天也没有得到太多的使用,因此任何在这种情况下为此目的工作的新API都是好的。可能是
    ExecutorService
    Future
  • 我不知道如何将这些数字合并一次并将结果返回给所有线程。通常我会
    加入
    它们,但我不能在线程外这样做,因为这会阻止同步响应,从而破坏整个想法
我正在寻找一种能够满足上述要求和要点的设计,类似于我在代码中所做的

  • groupMap是静态的,所以只要应用程序存在,它对所有调用都是相同的实例。但还没有创建实例。Java提供了同步的集合,因此您无需费心同步对它的访问:

    static Map<Long, Map<Long, Integer>> groupMap = Collections.synchronizedMap( new HashMap<>());
    

    看起来不错。周末后我会尝试一下,然后回来报告。顺便说一句,我认为ConcurrentHashMap会比Collections.synchronizedMap好。我不知道ConcurrentHashMap很好。毕竟,我认为最好为每个组使用一个单独的锁对象,如您在第2段中指出的链接,但仅用于同步对公共数据结构的访问(获取或添加客户机/期货和实际客户机数量)。
    static Map<Long, Map<Long, Integer>> groupMap = Collections.synchronizedMap( new HashMap<>());
    
    Map<Long, CompletableFuture> futures = Collections.synchronizedMap( new HashMap<>());
    
        CompletableFuture<Integer> future = new CompletableFuture<>();
        futures.put(clientId, future);
        int sum = future.get();
    
        futures.values().forEach( i -> i.complete( sum));