java吧 关注:1,271,963贴子:12,782,363
  • 8回复贴,共1

补全聊天室的线程调度部分。

只看楼主收藏回复

https://tieba.baidu.com/p/7371394533?pn=1
这里是上次说的状态机部分。
这里补全一下状态机调度的部分。


IP属地:安徽1楼2021-12-30 09:56回复
    为了方便大家了解,还是先从最外层的manager开始,
    manager里完成了整个状态机调度的过程,并对外暴露2个方法,进入,以及发送消息。


    IP属地:安徽2楼2021-12-30 09:59
    回复
      2025-07-31 21:40:00
      广告
      不感兴趣
      开通SVIP免广告
      线程调度





      IP属地:安徽3楼2021-12-30 10:02
      回复
        上面是创建\进入房间的代码
        创建一个EnterGroupTask, 交给CmdDispater完成进入房间的事情 (这一部分一会再说。)
        然后EnterGroupTask.run方法里调用findBestWorker2Enter。
        OK,这里先说说为什么要这样做。
        因为进入StateGroup,我们想尽快的进入,通过findDispatcher 可以让进入的行为负载到多个dispatcher执行。这样进入StateGroup就比较快了。
        考虑到StateGroup新建的情况,所以StateGroup有新旧之分,如果StateGroup是旧的,说明该StateGroup已经被分到,或者将要被分配到worker里,如果不是旧的,那需要给StateGroup安排worker线程去调度它。 这样就可以避免了一个StateGroup被多个worker调度的情况。保证了StateGroup的幂等性。
        同时,StateGroup的新与旧的判断是通过StateGroupPool里的ConcurrentHashMap.compute方法保证了原子性的操作。


        IP属地:安徽4楼2021-12-30 10:08
        回复
          在看看worker里的tryAddStateGroup方法。
          一个worker 可以调度多个StateGroup的方法,结合聊天、游戏等场景的延迟合理分配worker里的StateGroup的数量。
          比如StateGroup是一个聊天室,那么它的延迟可以稍微低一些,(在netty可支撑的最大的连接数的情况下),我们可以通过少量的worker线程来完成成百上千个聊天室的运行。
          所以,worker里的StateGroup的数量是需要严格把关的。
          那么如何保证worker不会超出?
          通过定义一个CurrentEnterStateGroup,并使用cas来保证 一个worker最多只能有一个StateGroup在enter。



          IP属地:安徽5楼2021-12-30 10:15
          回复
            再说说CommandDispatcher.
            它是一个指令发送器。负责将指令发送给StateGroup, 或者创建StateGroup,并帮助它进入到一个worker里。


            IP属地:安徽6楼2021-12-30 10:23
            回复
              大家在用linkedBlockQueue的时候,如果是批量执行,可以考虑用它的DrainTo方法一次性将数据拷贝到一个list里,可以减少因poll 这种方法带来的锁的开销。


              IP属地:安徽7楼2021-12-30 10:25
              回复
                mark


                IP属地:江苏来自iPhone客户端8楼2021-12-30 12:14
                收起回复