mina学习1

   

   在启动程序时,NioSocketAcceptor 绑定本地端口时,NioSocketAcceptor(AbstractPollingIoAcceptor<S,H>).startupAcceptor()  内部类为一个线程类,用来接收新socket链接。

  同时,Acceptor启动IoProcess线程来处理IO读取操作。


   Acceptor线程调用堆栈如下:


NamePreservingRunnable.<init>(Runnable, String)
NioSocketAcceptor(AbstractIoService).executeWorker(Runnable, String)
NioSocketAcceptor(AbstractIoService).executeWorker(Runnable)
NioSocketAcceptor(AbstractPollingIoAcceptor<S,H>).startupAcceptor()
NioSocketAcceptor(AbstractPollingIoAcceptor<S,H>).bindInternal(List<SocketAddress>)
NioSocketAcceptor(AbstractIoAcceptor).bind(Iterable<SocketAddress>)
NioSocketAcceptor(AbstractIoAcceptor).bind(SocketAddress) 


IoProcess线程启动如下:


SimpleIoProcessorPool<S>.<init>(Class<IoProcessor<S>>, Executor, int, SelectorProvider) line: 160    
SimpleIoProcessorPool<S>.<init>(Class<IoProcessor<S>>) line: 115    
NioSocketAcceptor(AbstractPollingIoAcceptor<S,H>).<init>(IoSessionConfig, Class<IoProcessor<S>>) line: 106    
NioSocketAcceptor.<init>() line: 61    


public abstract class AbstractPollingIoAcceptor

{

      /**
     * Define the number of socket that can wait to be accepted. Default
     * to 50 (as in the SocketServer default).
     */
    protected int backlog = 50;

    //构造函数
    protected AbstractPollingIoAcceptor(IoSessionConfig sessionConfig, Class<? extends IoProcessor<S>> processorClass)
    {
            this(sessionConfig, null, new SimpleIoProcessorPool<S>(processorClass), true, null);
    }


}

  //创造默认线程数量为CPU数量+1


    /** The pool table */
    private final IoProcessor<S>[] pool;  //在这里是创建IoProcess线程数组.

    /** The default pool size, when no size is provided. */
    private static final int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors() + 1;

   /**
     * Creates a new instance of SimpleIoProcessorPool with a default
     * size of NbCPUs +1.
     *
     * @param processorType The type of IoProcessor to use
     */
    public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType)

    {
            this(processorType, null, DEFAULT_SIZE, null);
    }

  public SimpleIoProcessorPool(Class<? extends IoProcessor<S>> processorType, Executor executor, int size, SelectorProvider selectorProvider) {
        if (processorType == null)

       {
            throw new IllegalArgumentException("processorType");
        }

        if (size <= 0) {
            throw new IllegalArgumentException("size: " + size + " (expected: positive integer)");
        }

        // Create the executor if none is provided
        createdExecutor = (executor == null);

        if (createdExecutor) {
            this.executor = Executors.newCachedThreadPool();
            // Set a default reject handler
            ((ThreadPoolExecutor) this.executor).setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        } else {
            this.executor = executor;
        }

        pool = new IoProcessor[size];

        boolean success = false;
        Constructor<? extends IoProcessor<S>> processorConstructor = null;
        boolean usesExecutorArg = true;

        try {
            // We create at least one processor
            try {
                try {
                    processorConstructor = processorType.getConstructor(ExecutorService.class);
                    pool[0] = processorConstructor.newInstance(this.executor);
                } catch (NoSuchMethodException e1) {
                    // To the next step...
                    try {
                        if(selectorProvider==null) {
                            processorConstructor = processorType.getConstructor(Executor.class);
                            pool[0] = processorConstructor.newInstance(this.executor);
                        } else {
                            processorConstructor = processorType.getConstructor(Executor.class, SelectorProvider.class);
                            pool[0] = processorConstructor.newInstance(this.executor,selectorProvider);
                        }
                    } catch (NoSuchMethodException e2) {
                        // To the next step...
                        try {
                            processorConstructor = processorType.getConstructor();
                            usesExecutorArg = false;
                            pool[0] = processorConstructor.newInstance();
                        } catch (NoSuchMethodException e3) {
                            // To the next step...
                        }
                    }
                }
            } catch (RuntimeException re) {
                LOGGER.error("Cannot create an IoProcessor :{}", re.getMessage());
                throw re;
            } catch (Exception e) {
                String msg = "Failed to create a new instance of " + processorType.getName() + ":" + e.getMessage();
                LOGGER.error(msg, e);
                throw new RuntimeIoException(msg, e);
            }

     
            //根据CPU数量来创建线程池中线程数量.默认最小为一个
            // Constructor found now use it for all subsequent instantiations
            for (int i = 1; i < pool.length; i++)
            {
                try {
                    if (usesExecutorArg) {
                        if(selectorProvider==null) {
                            pool[i] = processorConstructor.newInstance(this.executor);
                        } else {
                            pool[i] = processorConstructor.newInstance(this.executor, selectorProvider);
                        }
                    } else {
                        pool[i] = processorConstructor.newInstance();
                    }
                } catch (Exception e) {
                    // Won't happen because it has been done previously
                }
            }


            success = true;
        } finally {
            if (!success) {
                dispose();
            }
        }
    }

到此为止,Apache mina线程模型已经清晰。在创建 NioSocketAcceptor acceptor = new NioSocketAcceptor(); 并且绑定端口时,创建一个Acceptor线程用来接收新socket。

同时创建N个IoProcess用于处理IO操作。IoProcess线程默认数量为机器CPU数量+1.

每一个IoSession根据ID与线程池中索引顺序来关联。每一个IoSession有且只有一个关联的Process.

private void startupAcceptor() throws InterruptedException

{
  
        if (!selectable)

       {
            registerQueue.clear();
            cancelQueue.clear();
        }

        // start the acceptor if not already started
        Acceptor acceptor = acceptorRef.get();

        if (acceptor == null)

        {
            lock.acquire();
            acceptor = new Acceptor();

            if (acceptorRef.compareAndSet(null, acceptor))

            {
                    executeWorker(acceptor); //Acceptor线程在这里执行
            }

           else

             {
                lock.release();
            }
        }
    }


  protected final void executeWorker(Runnable worker, String suffix)
    {
        String actualThreadName = threadName;
        if (suffix != null)
        {
            actualThreadName = actualThreadName + '-' + suffix;
        }
        executor.execute(new NamePreservingRunnable(worker, actualThreadName));  //Acceptor为保存线程名称类,用来接收新socket接入
    }



  内部类Acceptor为处理新socket链接的主要类,代码如下:


    /**
     * This class is called by the startupAcceptor() method and is
     * placed into a NamePreservingRunnable class.
     * It's a thread accepting incoming connections from clients.
     * The loop is stopped when all the bound handlers are unbound.
     */
    //Acceptor类在AbstractIoAcceptor中用来启动Acceptor,一个NamePreseringRunnable类.
    //Acceptor用来处理新socket的链接。、
    //无限循环执行来判断是否有新socket链接进来
    private class Acceptor implements Runnable
    {
        public void run()
        {
            assert (acceptorRef.get() == this);
            //新socket的数量
            int nHandles = 0;
             //Acceptor类是一个NamePreservingRunable 类,用来处理新链接的socket
            // Release the lock
            lock.release();

            while (selectable)
            {
                try
                {
                    // Detect if we have some keys ready to be processed
                    // The select() will be woke up if some new connection
                    // have occurred, or if the selector has been explicitly
                    // woke up
                    //Acceptor执行select()函数来判断是否有新的链接进入socket
                    //阻塞函数,当select()返回时,有新socket进入
                    int selected = select();

                    // this actually sets the selector to OP_ACCEPT,
                    // and binds to the port on which this class will
                    // listen on
                    nHandles += registerHandles();

                    // Now, if the number of registred handles is 0, we can
                    // quit the loop: we don't have any socket listening
                    // for incoming connection.
                    if (nHandles == 0)
                    {
                        acceptorRef.set(null);

                        if (registerQueue.isEmpty() && cancelQueue.isEmpty())
                        {
                            assert (acceptorRef.get() != this);
                            break;
                        }

                        if (!acceptorRef.compareAndSet(null, this)) {
                            assert (acceptorRef.get() != this);
                            break;
                        }

                        assert (acceptorRef.get() == this);
                    }

                    if (selected > 0)
                    {
                        // We have some connection request, let's process
                        // them here.
                        //当select()函数执行完后,发现有新的socket进入.
                        //selected数量来判断新进入的socket,并且初始化IoSession和IoProcess相关联。一个socket有且只与一个socket相关联
                        processHandles(selectedHandles());
                    }


                    // check to see if any cancellation request has been made.
                    nHandles -= unregisterHandles();
                } catch (ClosedSelectorException cse) {
                    // If the selector has been closed, we can exit the loop
                    ExceptionMonitor.getInstance().exceptionCaught(cse);
                    break;
                } catch (Exception e) {
                    ExceptionMonitor.getInstance().exceptionCaught(e);
                   
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        ExceptionMonitor.getInstance().exceptionCaught(e1);
                    }
                }
            }
            //
            // 总结: 1、IoAcceptor线程,来处理接入的socket 然后,使IoSession和IoProcess相关联。多个IoProcess处理IoSession.但是一个IoSession仅仅对应一个IoProcess.并且IoAcceptor的线程数量为1.
            //     2、 IoPross线程。在SimpleIoProcessorPool中配置。  private static final int DEFAULT_SIZE = Runtime.getRuntime().availableProcessors() + 1;
            //        IoProcess线程数量默认设置为Mina内置配置。
            //     3、 IoHandler 逻辑处理和IoProcess IO线程是同一个线程。如果,IoHandler线程阻塞,将影响IO操作。同时,影响与该IoProcess相关联的所有IoSession.
            //     4、如果IoHandler会阻塞IoProcess线程,那么可以通过
            //
            /以上代码是Acceptor来处理新链接的socket//
            // Cleanup all the processors, and shutdown the acceptor.
            if (selectable && isDisposing())
            {
                selectable = false;
                try {
                    if (createdProcessor) {
                        processor.dispose();
                    }
                } finally {
                    try {
                        synchronized (disposalLock) {
                            if (isDisposing()) {
                                destroy();
                            }
                        }
                    } catch (Exception e) {
                        ExceptionMonitor.getInstance().exceptionCaught(e);
                    } finally {
                        disposalFuture.setDone();
                    }
                }
            }
        }
































 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值