【发布时间】:2017-07-20 18:19:35
【问题描述】:
我正在使用 JAX-RS 来处理客户端请求。场景是这样的:客户端被分成 5 个组。每个客户端需要向服务器提交一个数字,当属于同一组的所有 5 个客户端完成提交他们的数字时,服务器计算这些数字的总和并返回结果给他们所有人。
因为当客户端提交一个数字时,他们必须等待其他人也这样做(如果他们不是最后一个)我正在使用异步响应 API,它允许等待其他客户端而不会超载服务器.假设没有超时限制。
我对 JAX-RS 的内部工作原理、会话和上下文缺乏了解,这让我很难设计出合适的解决方案。这是我的想法(混合代码-伪代码):
public class SummationResource {
@Inject
SummationService service; // talks with the entity manager
//group client number
static Map<Long, Map<Long, Integer>> groupMap;
@POST
@Path("{clientId}")
public void submit(int num,
@PathParam("clientId") long clientId,
@Suspended AsyncResponse response) {
new Thread() {
@Override
public void run() {
long groupId = service.getGroupOfClient(clientId);
Map<Long, Integer> clients = groupMap.get(groupId);
clients.put(clientId, num);
if (clients.size() != 5)
// wait (see points below)
else
// release all threads of this group
int sum = HelperClass.sum(clients.values()); // should be executed only once
response.resume(sum);
}
}.start();
}
}
我想触摸的点:
- 我知道我可以将它存储在数据库中而不是内存中,但是假设客户端之间的提交时间很短,并且从数据库中写入和读取的成本更高。
groupMap对于提交的每次调用是否不同(由不同的客户端)?使其静态足以让它在所有实例之间共享? - 为了同步线程,我可以创建一个
Map<Long, Object> locks,它将一个组ID 映射到一个同步的锁对象。所以每个线程通过调用locks.get(groupId).wait()来等待,释放行是locks.get(groupId).notifyAll()。锁对象由属于组的第一个线程创建。我不知道这种方法对 JAX-RS 和 AsyncResponse 是否友好。等待通知今天也没有太多使用,因此在这种情况下为此目的工作的任何新 API 都是好的。也许是ExecutorService和Future? - 我不确定如何将这些数字组合一次并将结果返回给所有线程。通常我会
join他们,但我不能在线程之外这样做,因为这会阻止同步响应,从而破坏整个想法。
我正在寻找一种能够解决上述请求和要点的设计,类似于我在代码中所做的。
【问题讨论】:
标签: java jakarta-ee jax-rs thread-synchronization