客户端向服务器发送匹配请求,服务端接收后将客户端Session放入匹配队列中,匹配完成时通知用户。
使用观察者设计模式可以实现这个功能。
观察者代码:
Java util 包拥有Observer 接口,这里根据实际应用自定义参数 Map。
import java.util.Map; ? public interface Observer { ? public void update(Map<String, String> map); ? }
被观察者接口:
import java.util.List; ? public interface Observerable { ? public void registerObserver(MatchNode o); ? public void removeObserver(MatchNode o); ? public void notifyObserver(List<MatchNode> matchNodes); ? ? }
每个节点存放用户数据,用于进行匹配和查找。
import java.util.Map; ? public class MatchNode implements Observer { ? private Long userId; ? private Long sessionId; ? private Long ruleId; ? ? ? public Long getUserId() { return userId; } ? public void setUserId(Long userId) { this.userId = userId; } ? public Long getSessionId() { return sessionId; } ? public void setSessionId(Long sessionId) { this.sessionId = sessionId; } ? public Long getRuleId() { return ruleId; } ? public void setRuleId(Long ruleId) { this.ruleId = ruleId; } ? ? @Override public void update(Map<String, String> map) { ? } }
使用被观察接口 registerObserver 和 registerObserver 可以对匹配队列中的用户进行管理,当匹配成功后,会将两个匹配成功的用户移除匹配集合,并对匹配成功的用户发送通知。
使用单例模式意味着可以在任意位置获取匹配线程的状态,在程序初始化时启动匹配线程即可。
用户在匹配成功时,由匹配线程生成一个 groupId 用于标记这对用户,可以通过groupId 在后续功能开发中可以起到查询的作用。
package common.thread; ? import cn.hutool.core.util.IdUtil; import common.util.RandomTable; import lombok.extern.slf4j.Slf4j; ? import java.util.*; import java.util.stream.Collectors; ? @Slf4j public class MatchQueueThread implements Runnable, Observerable { ? List<MatchNode> matchNodes; ? ? @Override public void registerObserver(MatchNode o) { matchNodes.add(o); } ? @Override public void removeObserver(MatchNode o) { if (!matchNodes.isEmpty()) matchNodes.remove(o); } ? @Override public void notifyObserver(List<MatchNode> matchNodes) { //从匹配队列中移除 this.matchNodes.removeAll(matchNodes); String groupId = IdUtil.randomUUID(); Map<String, String> dataMap = new HashMap<>(); dataMap.put("groupId", groupId); dataMap.put("tables", RandomTable.randomTableSerial()); matchNodes.forEach(matchNode -> { matchNode.update(dataMap); }); } ? //单例 private static class SingletonClassInstance { private static final MatchQueueThread instance = new MatchQueueThread(); } ? private MatchQueueThread() { matchNodes = new ArrayList<>(); } ? public static MatchQueueThread getInstance() { return SingletonClassInstance.instance; } ? public int getMatchCount() { return matchNodes.size(); } ? /** * | * 匹配逻辑 */ @Override public void run() { Map<Long, List<MatchNode>> result = matchNodes.parallelStream() .collect(Collectors.groupingBy(MatchNode::getRuleId)); for (Map.Entry<Long, List<MatchNode>> group : result.entrySet()) { if (group.getValue().size() > 1) { List<MatchNode> matchNodes = group.getValue().subList(0, 2); notifyObserver(matchNodes); log.info("匹配成功 : " + matchNodes.get(0).getUserId() + " " + matchNodes.get(1).getUserId()); } } } }
原文:https://www.cnblogs.com/yangchaojie/p/12269595.html