请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

为什么这里要重复调用readNextMessage()?

按照我的理解是readNextMessage只需要调用一次,然后有消息来的时候这个onCompleted方法就会被调用,我的理解问题出在哪?图片描述

正在回答

2回答

Qiujuer 2019-05-11 21:39:59

这个地方在于对于Selector的理解。

当我们在Selector上注册一个监听后,如果事件就绪就会从select方法中得到。此时可以进行事件处理。
但是这里有一个较大的问题,如果在多并发的情况下,我们一个线程专门负责Selector.select()操作,那么当有通道就绪时此时我们不断的调用Selector.select()将每次都得到这个就绪的通道。

我们的流程是:A线程Selector.select()得到就绪通道,将通道丢进线程池,等待线程池中的线程 B、C、D等运行。这个过程肯定不是单线的,而是多并发的。

那么当线程池还没处理完这个事件之前,我们每次Selector.select()都会得到这个通道;然后又会重复丢进线程池;这就有矛盾了,一旦发生这样的事情,那么就会出现同一个通道的数据被多个线程同时操作的情况,也就会出现数据混乱问题。对于一段字符串:“Hello”可能一个线程读取了其中一部分。但是却无法正确组合在一起。


那么这个时候我们在Selector.select()之后就做了一件事件,将已就绪的通道全部解除注册,那么下一次调度Selector.select()就不会得到这些就绪的通道了,从而避免上述问题。


当然这样的做法就需要有一个完整的闭环:

注册-等到Selector.select()-已就绪-解除注册-丢进线程池-等待线程调度-处理调度-读取数据-再次注册下一次调度


所以我们需要在完成方法调度时再次调用:

readNextMessage




0 回复 有任何疑惑可以回复我~
  • 提问者 树那边 #1
    好的,理解了谢谢老师,那么如果已就绪的通道全部解除注册,这时这些解除注册的通道对应的客户端有消息来了就得不到监听了,这些消息会被遗弃掉吗?还是说当这些通道重新注册时(如果之前有消息来了)又会处于就绪状态?0
    回复 有任何疑惑可以回复我~ 2019-05-11 23:02:15
提问者 树那边 2019-05-11 23:01:09

好的,理解了谢谢老师,那么如果已就绪的通道全部解除注册,这时这些解除注册的通道对应的客户端有消息来了就得不到监听了,这些消息会被遗弃掉吗?还是说当这些通道重新注册时(如果之前有消息来了)又会处于就绪状态?

0 回复 有任何疑惑可以回复我~
  • Qiujuer #1
    是的,消息不会丢,本地读取会读取完全,如果本次读取没有读取完全,再次注册会继续返回已就绪。
    回复 有任何疑惑可以回复我~ 2019-05-11 23:27:58
  • 提问者 树那边 回复 Qiujuer #2
    好的,谢谢!
    回复 有任何疑惑可以回复我~ 2019-05-11 23:36:20
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信