情境
我将尽可能简洁.基本上参考classdiag,我有一个外观管理一个SocketManager列表(管理一个Socket连接).每个SocketManager使用唯一的SocketUserId登录到远程服务器.此外,每个SocketManager都会接受来自客户端的消息,这些消息发往特定的收件人列表.为了便于讨论,请将这些接收方视为由名称标识的远程数据段.
客户将发送如下数据:
SocketFacade facade = ...;
byte[] data = ...
facade.sendData( receipient, data );
当SocketFacade启动时,它将查询一个mysql表,该表返回SocketUserId和Receipients之间的1-m关系.我将使用MultiValuedMap表示这种1-m关系.然后,将通过遍历映射来启动多个SocketManager.
(1) Map< SocketUserId, List<Receipient> >
例如假设我们有2个SocketManager,其SocketUserIds为“ alice”&分别为“ tom”
+----SocketManager1 ( "alice" ) for Receipients { "B", "C" }
|
SocketFacade
|
+----SocketManager2 ( "tom" ) for Receipients { "A", "D" }
题
关于如何实现sendData方法,我处于困境.基本上,我需要一种从接收者(例如“ B”)映射到其负责的SocketManager(例如SocketManager1)的方法.
假设我这样做
(2) Map< SocketUserId, SocketManager >
(3) Map< Receipient, SocketUserId >
>(2)中的值是否需要SoftReference?
>我是否应该直接从Receipient映射到SocketManager?
> SocketFacade还支持将使(1)表示的关系发生变异的方法.如果我写入数据库,则(1),(2)和& (3)将需要同步更改. SocketFacade也必须是线程安全的.最初的想法是拥有某种发布订阅系统,通过该系统,对数据库的添加/删除将导致更改通过回调传播.
interface Callback
{
void receipientAdded( Receipient r );
void receipientDeleted( Receipient r );
}
解决方法:
在每个收件人中保留对SocketManager的引用.这样,您就可以避免映射(它需要更多的RAM,速度较慢,并且不添加任何值).
在SocketManager中,保留收件人列表.添加和删除接收方时,请更新指向SocketManager的指针.
在SocketFacade中,您需要一个使用SocketUserId并返回SocketManager的映射.该地图是通过查询地图中的ID来填充的.所有经理都存在后,将收件人添加到每个中.这需要两个SQL查询.
使用任何ORM工具都非常容易映射.