mina源码学习之接收线程

创建完接收器IoAcceptor之后,紧接着就是启动服务端的监听,准备接受客户端的请求。启动监听的入口是IoAcceptor接口的bind方法,方法的实现在AbstractIoAcceptor类中,具体的逻辑处理是AbstractPollingIoAcceptor类的bindInternal方法。我们重点看下bindInternal方法中调用startupAcceptor方法启动接收线程的过程。

private void startupAcceptor() throws InterruptedException {
        // If the acceptor is not ready, clear the queues
        // TODO : they should already be clean : do we have to do that ?
        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);
            } else {
                lock.release();
            }
        }
    }

其中selectable的值在创建IoAcceptor的时候被置为true,那么清空两个队列的操作便不会执行。接着从AtomicReference对象中获取Acceptor的值,如果获取到的Acceptor值为空的话,则会创建一个Acceptor对象。注意Acceptor是接收请求的线程,而IoAcceptor是一个接口,表示服务端的接收器。创建完Acceptor线程之后通过acceptorRef的compareAndSet方法比较acceptorRef是否为空,如果是的话acceptorRef的值会被更新为刚创建的Acceptor线程的值,由于compareAndSet的操作线程安全的,因此比较,更新这两步操作是原子性的。设置完acceptorRef的值便会将Acceptor线程添加到接收线程池中,并且启动Acceptor线程。Acceptor线程主要功能实现代码如下:

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
                    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.
                        processHandles(selectedHandles());
                    }

                    // check to see if any cancellation request has been made.
                    nHandles -= unregisterHandles();
                }

其中select方法是一个阻塞模式的方法,返回准备就绪的键的数目,仅在至少选择一个通道、调用此选择器的 wakeup 方法,或者当前的线程已中断(以先到者为准)后此方法才返回。registerHandles和unregisterHandles从字面上来看就是两个功能相对的方法,registerHandles方法中封装了基本的NIO操作,比如打开通道,绑定监听端口,将ServerSocketChannel注册到选择器Selector上,监听Accept事件等。而unregisterHandles则是取消通道注册在选择器Selector上的Accept事件,关闭通道等。当select方法返回的值大于0时,也就是产生了Accept事件,说明收到了客户端的连接请求,这时将会调用processHandles方法启动I/O处理线程IoProcessor处理请求。
关于IoProcessor的部分下回继续分解。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值