zoukankan      html  css  js  c++  java
  • Mina2.0框架源码剖析(二)

    上一篇介绍了几个核心的接口,这一篇主要介绍实现这些接口的抽象基类。首先是实现IoService接口的AbstractIoService类。它包含了一个Executor来处理到来的事件。每个AbstractIoService都一个AtomicInteger类型的id号,确保每个id的唯一性。

    它内部的Executor可以选择是从外部传递进构造函数中,也可以在实例内部自行构造,若是后者,则它将是ThreadPoolExecutor类的一个实例,即是Executor线程池中的一员。代码如下:

         if (executor == null) 
            {
                this.executor = Executors.newCachedThreadPool();
                createdExecutor = true;
            } 
            else 
            {
                this.executor = executor;
                createdExecutor = false;
            }

          其中有一个IdleStatusChecker成员,它用来对服务的空闲状态进行检查,在一个服务激活时会将服务纳入到检查名单中,而在服务失效时会将服务从名单中剔除。会单独开一个线程进行具体的空闲检查,这是通过下面这个线程类来负责的:

    private class NotifyingTaskImpl implements NotifyingTask 
    {
            private volatile boolean cancelled;//取消检查标志
            private volatile Thread thread;
            public void run()
    {
                thread = Thread.currentThread();
                try {
                    while (!cancelled) 
    {
                        //每隔1秒检查一次空闲状态
                        long currentTime = System.currentTimeMillis();
                        notifyServices(currentTime);
                        notifySessions(currentTime);
                        try 
    {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) 
    {
                            // will exit the loop if interrupted from interrupt()
                        }
                    }
                }
     Finally
     {
                    thread = null;
                }
            }
    }

    具体的空闲检查代码如下,超过能容忍的最大空闲时间,就会fire出SessionIdle事件,上文也说过空闲有三种类型:读端空,写端空,双端空。

    notifyIdleSession1(s, currentTime,
                    s.getConfig().getIdleTimeInMillis(IdleStatus.BOTH_IDLE),IdleStatus.BOTH_IDLE,Math.max(s.getLastIoTime(),s.getLastIdleTime(IdleStatus.BOTH_IDLE)));
        private static void notifyIdleSession1(
                AbstractIoSession session, long currentTime,
                long idleTime, IdleStatus status, long lastIoTime) 
    {
            if (idleTime > 0 && lastIoTime != 0
                    && currentTime - lastIoTime >= idleTime) 
    {
                session.getFilterChain().fireSessionIdle(status);
            }
    }

         在释放资源的方法时,首先去获取释放锁disposalLock才行,然后具体的释放动作是通过dispose0完成的,接着取消掉空闲检查线程,此外,若线程是内部创建的线程池中的一员,则通过线程池去关闭线程。

       public final void dispose() 
    {
            IoFuture disposalFuture;
            synchronized (disposalLock) 
    {//获取释放锁
                disposalFuture = this.disposalFuture;
                if (!disposing) {
                    disposing = true;
                    try {
                        this.disposalFuture = disposalFuture = dispose0();//具体释放动作
                    } catch (Exception e) {
                        ExceptionMonitor.getInstance().exceptionCaught(e);
                    } finally {
                        if (disposalFuture == null) {
                            disposed = true;
                        }
                    }
                }
            }
            idleStatusChecker.getNotifyingTask().cancel();
            if (disposalFuture != null)
    {//无中断地等待释放动作完成
                disposalFuture.awaitUninterruptibly();
            }
            if (createdExecutor) 
    {通过线程池去关闭线程
                ExecutorService e = (ExecutorService) executor;
                e.shutdown();
                while (!e.isTerminated()) {
                    try {
                        e.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
                    } catch (InterruptedException e1) {
                        // Ignore; it should end shortly.
                    }
                }
            }
            disposed = true;
        }

         再来看会话初始化完成后的动作每个session都保持有自己的属性映射图,在会话结束初始化时,应该设置这个AttributeMap。

    ((AbstractIoSession) session).setAttributeMap(session.getService()
                        .getSessionDataStructureFactory().getAttributeMap(session));

         除此以为,还应该为会话配置写请求队列:

    ((AbstractIoSession) session).setWriteRequestQueue(session
                        .getService().getSessionDataStructureFactory()
                        .getWriteRequestQueue(session));

         在初始化时会在会话的属性中加入一项SESSION_CREATED_FUTURE,这个属性会在连接真正建立后从会话中去除。

            if (future != null && future instanceof ConnectFuture) 
    {
               session.setAttribute(DefaultIoFilterChain.SESSION_CREATED_FUTURE,
                        future);
     }

    用户特定的初始化动作在finishSessionInitialization0这个方法中自行实现。

    作者:phinecos(洞庭散人)
    出处:http://phinecos.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,并在文章页面明显位置给出原文连接。

  • 相关阅读:
    一、编程语言
    1、计算机基础
    四、格式化输出与基本运算符
    二、变量及用户与程序互交
    三、基本数据类型
    查看静态库中有哪些函数
    vs2010 error MSB6006: “cmd.exe”已退出,代码为 1
    ffmpeg formats
    C#启动一个外部程序(3)CreateProcess
    C#启动一个外部程序(2)ShellExecute
  • 原文地址:https://www.cnblogs.com/pampam/p/5135133.html
Copyright © 2011-2022 走看看