请稍等 ...
×

采纳答案成功!

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

思维导图帮助理解

看了三遍,终于理解了,下面把我遇到的问题发一下;
很多小伙伴都说第七章跨度大,我也是,刚开始我也是一脸蒙蔽,老师突然就讲解 clink 几个核心类了,突然有点不知所措,所以在听第一遍的时候,都有点懵,so do i ,但看了第二遍之后,就有些理解了,下面一起分析一下;

一、优化方向

老师这里的优化,只是对 服务端中的 ClientHandler 中的数据监听进行了优化,先抓住这个点,假如让你去优化 拿到客户端的数据,你怎么去优化,怎么去解耦;带着这个问题入手,会方便很多。

二、怎么优化

理解之后,觉得老师对解耦的处理非常棒;先看流程图:
图片描述

然后看 imple,即 SocketChannelAdapter 和 IoSelectorProvider;
SocketChannelAdapter :
数据的读写肯定得拿到 SocektChannel ,拿到之后配置非阻塞模式,然后它的 OP_READ 和 OP_WRITE 是通过继承 sender 和 receiver 接口,把具体的实现交给 IoSelectorProvider。如:

    @Override
    public boolean receiverAsync(IoArgs.IoArgsEventListener listener) throws IOException {
        if (isClosed.get()){
            throw new IOException("Current channel is closed!");
        }
        receiverEventListener = listener;
        //读注册给 ioprovider,让它完成具体的实现
        return ioProvider.registerInput(channel,inputCallback);
    }

IoSelectorProvider:
这里才是 需要关注的点,在 SocketChannelAdapter 已经把注册的事件专递给 IoSelectorProvider 了,所以,也看 register 部分:

    @Override
    public boolean registerInput(SocketChannel channel, HandleInputCallback callback) {
        return  registerSelection(channel,readSelector,
                SelectionKey.OP_READ,inRegInput,inputCallbackMap,callback) != null;
    }

这里的注册,其实就是把当前的channel 的 OP_READ 事件,去检测是否已经注册,没有就先注册到 selector 中,并把当前的 selectionKey 和 Runnable 放到 map 中。如下具体实现

    /**
     * 注册 selection
     * @param channel
     * @param selector
     * @param registerOps
     * @param locker ,多线程,需要等待注册完成,才能去遍历和拿到数据,所以用原子锁
     * @param map
     * @param runnable
     * @return
     */
    private static SelectionKey registerSelection(SocketChannel channel,Selector selector,
                                                  int registerOps,AtomicBoolean locker,
                                                  HashMap<SelectionKey,Runnable> map,
                                                  Runnable runnable){
        synchronized (locker){
            //设置锁定状态
            locker.set(true);
            try {
                //唤醒 selector,让selector不处于 select() 状态
                selector.wakeup();
                //如果 channel 已经有注册过东西
                SelectionKey key;
                if (channel.isRegistered()){
                    key = channel.keyFor(selector);
                    //如果已经该 key 已经被注册过了
                    if (key != null){
                        //把key重新加入
                        key.interestOps(key.interestOps() | registerOps);
                    }
                }else{
                    //如果还没有被注册过
                    key = channel.register(selector, registerOps);
                    //并把当前的 key 和 runnable 填充到map
                    map.put(key,runnable);
                }

                return key;
            } catch (Exception e) {
               // e.printStackTrace();
            }finally {
                //解除锁定,表示注册完成
                locker.set(false);
            }
        }
        return null;
    }

最后,再去理解 startRead 里面的方法,就比较简单了,就是把 selector 中拿到的 selectionkey 与 map 中对比,若存在,则用线程池去启动即可。

注意! IoConntext 的 setUp 方法,被写成静态类且在main函数中启动,所以IoSelectorProvider只被初始化一次,而SocketChannelAdapter 是每次有新客户端过来时,就会重新注册一个。所以老师在 IoSelectorProvider 中才对线程等待同步这块做了优化;

那换成是你,你怎么抽离和优化这块部分呢?

正在回答 回答被采纳积分+3

2回答

Qiujuer 2019-08-16 09:36:18

非常棒~~~ 同学学的不错哦,我给你置顶了,帮助更多的 同学。

1 回复 有任何疑惑可以回复我~
  • 提问者 LillteZheng #1
    老师,我这边又有疑惑了,看到您在课程里,用了很多观察者模式,这里有个疑问;在 SocketChannelAdapter 中通过集成 Sender 和 Receiver ,并实现接口方法;然后在 Connector 中又通过初始化 SocketChannelAdapter  之后,又重新给了 sender 和receiver,再用 receiver 和sender 去调用各自的方法;那为什么,不直接用 SocketChannelAdapter  直接调用receiverAsync呢?老师方便解释一下为啥要这么设计吗?有点转不过来
    回复 有任何疑惑可以回复我~ 2019-08-16 17:14:17
  • Qiujuer 回复 提问者 LillteZheng #2
    这里的主要目的是想要做一层上层的抽象。简单来说经过抽象后对于上层来说只需要关注两个东西:发送者、接收者。至于发送者究竟是谁,接受者究竟是谁而不必去关注,这样的好处是,我们要去动Socket传输层的东西的时候不必惊动上层的调度,从而实现分离。
    
    只是在咱们的这里是把sender和receiver都放到了一起,其实这两个完全可以分开,甚至可以建立两个socket,一个用来收,一个发,都是可以的。
    回复 有任何疑惑可以回复我~ 2019-08-16 23:47:35
  • 提问者 LillteZheng 回复 Qiujuer #3
    明白了,谢谢老师,以后也多往这方面想
    回复 有任何疑惑可以回复我~ 2019-08-17 17:23:47
提问者 LillteZheng 2019-08-15 14:56:22

如有错误,欢迎指正,谢谢

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信