代码拉取完成,页面将自动刷新
我觉得我找到了jim-client的一个bug,但是不知道该怎么改。
public ImClientChannelContext connect(Node serverNode, Integer timeout) throws Exception {
log.warn("J-IM client connect");
tioClient = new TioClient((ClientTioConfig) imClientConfig.getTioConfig());
ClientChannelContext clientChannelContext = tioClient.connect(serverNode, imClientConfig.getBindIp(), imClientConfig.getBindPort(), timeout);
if(Objects.nonNull(clientChannelContext)){
log.warn("J-IM client connected success at serverAddress:[{}], bind localAddress:[{}]", serverNode.toString(), imClientConfig.toBindAddressString());
return (ImClientChannelContext)clientChannelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY);
}
return null;
}
里面的 clientChannelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY);
这一行 很大的概率返回null
也就是 工程中
channelContext.set(Key.IM_CHANNEL_CONTEXT_KEY, imChannelContext); 执行的顺序 在 clientChannelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY); 之后,我看到里面操作的是一个map,
private final MapWithLock<String, Object> props = new MapWithLock(new HashMap(8));
应该是多线程导致的
"不是很大的概率" 是 有一定的概率,跟机器有关系。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
再往下跟了一下,我想问题应该在这里
CountDownLatch countDownLatch = new CountDownLatch(1);
attachment.setCountDownLatch(countDownLatch);
asynchronousSocketChannel.connect(inetSocketAddress, attachment, this.clientTioConfig.getConnectionCompletionHandler());
boolean f = countDownLatch.await((long)realTimeout, TimeUnit.SECONDS);
if (f) {
return attachment.getChannelContext();
} else {
log.error("countDownLatch.await(realTimeout, TimeUnit.SECONDS) 返回false ");
return attachment.getChannelContext();
}
这里有一个睡眠,但是睡的不够
这里有好几个线程,貌似没有做线程的同步
最后解决了,底层不敢改,只敢改上层的东西。
重写写了一个类 WJimCient(里面基本复制的JimClient中的内容)
/***
* auth: robin
* date: 2021/01/21
* 这里基本复制的JimClient,没直接用JimClient的原因是,
* clientChannelContext.get("im_channel_context_key") 很大的概率会返回null,
* 因为里面有个map,赋值是通过多线程来完成的,如果另一个线程没有赋值的话,这里得到的就是null
*
*/
public class WJimClient {
private static Logger log = LoggerFactory.getLogger(JimClient.class);
private TioClient tioClient = null;
private ImClientConfig imClientConfig;
public WJimClient(ImClientConfig imClientConfig) {
this.imClientConfig = imClientConfig;
}
public ImClientChannelContext connect(Node serverNode) throws Exception {
return this.connect(serverNode, (Integer)null);
}
public ImClientChannelContext connect(Node serverNode, Integer timeout) throws Exception {
log.warn("J-IM client connect");
this.tioClient = new TioClient((ClientTioConfig)this.imClientConfig.getTioConfig());
ClientChannelContext clientChannelContext = this.tioClient.connect(serverNode, this.imClientConfig.getBindIp(), this.imClientConfig.getBindPort(), timeout);
if (Objects.nonNull(clientChannelContext)) {
log.warn("J-IM client connected success at serverAddress:[{}], bind localAddress:[{}]", serverNode.toString(), this.imClientConfig.toBindAddressString());
ImClientChannelContext t_rtnContext = (ImClientChannelContext)clientChannelContext.get("im_channel_context_key");
int t_maxCount = 200; //最大循环次数,实际测试中只循环了一次
while (null == t_rtnContext
&& t_maxCount > 0){//这里是在等待另一个线程写入
Thread.sleep(50);
t_rtnContext = (ImClientChannelContext)clientChannelContext.get("im_channel_context_key");
t_maxCount--;
}
System.out.println("robin:count:"+(200-t_maxCount));
return t_rtnContext;
} else {
return null;
}
}
public void stop() {
this.tioClient.stop();
}
}
登录 后才可以发表评论