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;
                }
            }
    }

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

    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/
    本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,并在文章页面明显位置给出原文连接。

    作者:洞庭散人

    出处:http://phinecos.cnblogs.com/    

    本博客遵从Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。
  • 相关阅读:
    javaweb学习总结(三十七)——获得MySQL数据库自动生成的主键
    javaweb学习总结(三十六)——使用JDBC进行批处理
    JavaWeb学习总结(三十五)——使用JDBC处理Oracle大数据
    javaweb学习总结(三十四)——使用JDBC处理MySQL大数据
    javaweb学习总结(三十三)——使用JDBC对数据库进行CRUD
    javaweb学习总结(三十二)——JDBC学习入门
    javaweb学习总结(三十一)——国际化(i18n)
    javaweb学习总结(二十九)——EL表达式
    javaweb学习总结(二十八)——JSTL标签库之核心标签
    javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Invalid property in <set>: "age2"
  • 原文地址:https://www.cnblogs.com/phoebus0501/p/1878883.html
Copyright © 2011-2022 走看看