Apache Mina 源码再读 1 Bind过程以及DefaultIoFuture源码

1 、bind 事件  

在服务器端调用public final void bind(SocketAddress... addresses) throws IOException 方法绑定本地端口时,

仔细看看,Apache Mina 在bind()本地端口做了哪些事情?


 protected final Set<SocketAddress> bindInternal(List<? extends SocketAddress> localAddresses) throws Exception {
        // Create a bind request as a Future operation. When the selector
        // have handled the registration, it will signal this future.
        AcceptorOperationFuture request = new AcceptorOperationFuture(localAddresses);

        // adds the Registration request to the queue for the Workers
        // to handle
        registerQueue.add(request);

        // creates the Acceptor instance and has the local
        // executor kick it off.
        startupAcceptor();

        // As we just started the acceptor, we have to unblock the select()
        // in order to process the bind request we just have added to the
        // registerQueue.
        try {
            lock.acquire();

            // Wait a bit to give a chance to the Acceptor thread to do the select()
            Thread.sleep(10);
            wakeup();
        } finally {
            lock.release();
        }

        // Now, we wait until this request is completed.
        request.awaitUninterruptibly();

        if (request.getException() != null) {
            throw request.getException();
        }

        // Update the local addresses.
        // setLocalAddresses() shouldn't be called from the worker thread
        // because of deadlock.
        Set<SocketAddress> newLocalAddresses = new HashSet<SocketAddress>();

        for (H handle : boundHandles.values()) {
            newLocalAddresses.add(localAddress(handle));
        }

        return newLocalAddresses;
    }


创建一个Bind事情请求,这事情请求是Future 操作。异步操作。然后select循环会处理这个bind事情,然后通知结果。


AcceptorOperationFuture 是一个异步Future操作. AcceptorOperationFuture 继承了DefaultIoFuture 类。这是一个Apache Mina 对于Future操作的内部实现。

org.apache.mina.core.future 包里面有多种Future操作。

其中包括:

1、 CloseFuture 

2、ConnectFuture 

3、ReadFuture   

4、WriteFuture 

以及这些Future的默认实现。 同时,对这些异步操作,future包中也定义了对应的事件监听器。IoFutureListener ,当Future操作完成时,触发IoFutureListener监听器。



/**
 * Something interested in being notified when the completion
 * of an asynchronous I/O operation : {@link IoFuture}. 
 *
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public interface IoFutureListener<F extends IoFuture> extends EventListener {
    /**
     * An {@link IoFutureListener} that closes the {@link IoSession} which is
     * associated with the specified {@link IoFuture}.
     */
    static IoFutureListener<IoFuture> CLOSE = new IoFutureListener<IoFuture>() {
        public void operationComplete(IoFuture future) {
            future.getSession().close(true);
        }
    };

    /**
     * Invoked when the operation associated with the {@link IoFuture}
     * has been completed even if you add the listener after the completion.
     *
     * @param future  The source {@link IoFuture} which called this
     *                callback.
     */
    void operationComplete(F future);
}

       // Create a bind request as a Future operation. When the selector
        // have handled the registration, it will signal this future.
        AcceptorOperationFuture request = new AcceptorOperationFuture(localAddresses);


通过以上代码,创建了一个Future 异步操作。然后,把Future保存到队列中,然select 异步来操作完成AcceptorOperation的事件.


        // adds the Registration request to the queue for the Workers
        // to handle
        registerQueue.add(request);


    private final Queue<AcceptorOperationFuture> registerQueue = new ConcurrentLinkedQueue<AcceptorOperationFuture>();


    // creates the Acceptor instance and has the local
        // executor kick it off.
        startupAcceptor();

然后通过startAcceptor()方法来启动一个Acceptor 线程。



        // As we just started the acceptor, we have to unblock the select()
        // in order to process the bind request we just have added to the
        // registerQueue.
        try {
            lock.acquire();


            // Wait a bit to give a chance to the Acceptor thread to do the select()
            Thread.sleep(10);
            wakeup();
        } finally {
            lock.release();
        }


然后通过lock信号量,通过当前线程Thread.sleep(10),来让另外一个线程来完成AcceptorOperation操作。


 // Now, we wait until this request is completed.
        request.awaitUninterruptibly();

最后一直等到AcceptorOperationFuture异步操作的完成。 这个是异步转换成同步的方式。


异步转换同步,可以通过object.await() 、object.notifyAll()来实现。这个主要看DefaultIoFuture 源代码。



在Acceptor 线程中有一个registerHandles()方法时专门来处理AcceptorOperationFuture 操作。


    private int registerHandles() 
    {
        for (;;) 
        {
            // The register queue contains the list of services to manage
            // in this acceptor.
            AcceptorOperationFuture future = registerQueue.poll();

            if (future == null)
            {
                return 0;
            }

            // We create a temporary map to store the bound handles,
            // as we may have to remove them all if there is an exception
            // during the sockets opening.
            Map<SocketAddress, H> newHandles = new ConcurrentHashMap<SocketAddress, H>();
            List<SocketAddress> localAddresses = future.getLocalAddresses();

            try 
            {
                // Process all the addresses
                for (SocketAddress a : localAddresses)
                {
                    H handle = open(a);
                    newHandles.put(localAddress(handle), handle);
                }

                // Everything went ok, we can now update the map storing
                // all the bound sockets.
                boundHandles.putAll(newHandles);

                // and notify.
                future.setDone();
                return newHandles.size();
                
                ///以上代码判断新链接的socket数量///
            } catch (Exception e) {
                // We store the exception in the future
                future.setException(e);
            } finally {
                // Roll back if failed to bind all addresses.
                if (future.getException() != null) {
                    for (H handle : newHandles.values()) {
                        try {
                            close(handle);
                        } catch (Exception e) {
                            ExceptionMonitor.getInstance().exceptionCaught(e);
                        }
                    }

                    // TODO : add some comment : what is the wakeup() waking up ?
                    wakeup();
                }
            }
        }
    }

registerHandles()方法来迭代registerQueue 队列。 registerQueue队列是线程安全的。registerQueue队列被调用bind()线程和Acceptor线程共同访问。


当Accept事件完成时,会调用Future.setDone()来通知bind()线程停止等待。



在这个阶段中DefaultIoFuture 类实现了类似JDK  Future 模型。 我们重点学习一下DefaultIoFuture 类的功能。



2、DefaultIoFuture源码剖析


/**
 * Represents the completion of an asynchronous I/O operation on an 
 * {@link IoSession}.
 * Can be listened for completion using a {@link IoFutureListener}.
 * 
 * @author <a href="http://mina.apache.org">Apache MINA Project</a>
 */
public interface IoFuture {
    /**
     * Returns the {@link IoSession} which is associated with this future.
     */
    IoSession getSession();

    /**
     * Wait for the asynchronous operation to complete.
     * The attached listeners will be notified when the operation is 
     * completed.
     */
    IoFuture await() throws InterruptedException;

    /**
     * Wait for the asynchronous operation to complete with the specified timeout.
     *
     * @return <tt>true</tt> if the operation is completed.
     */
    boolean await(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * Wait for the asynchronous operation to complete with the specified timeout.
     *
     * @return <tt>true</tt> if the operation is completed.
     */
    boolean await(long timeoutMillis) throws InterruptedException;

    /**
     * Wait for the asynchronous operation to complete uninterruptibly.
     * The attached listeners will be notified when the operation is 
     * completed.
     * 
     * @return the current IoFuture
     */
    IoFuture awaitUninterruptibly();

    /**
     * Wait for the asynchronous operation to complete with the specified timeout
     * uninterruptibly.
     *
     * @return <tt>true</tt> if the operation is completed.
     */
    boolean awaitUninterruptibly(long timeout, TimeUnit unit);

    /**
     * Wait for the asynchronous operation to complete with the specified timeout
     * uninterruptibly.
     *
     * @return <tt>true</tt> if the operation is finished.
     */
    boolean awaitUninterruptibly(long timeoutMillis);

    /**
     * @deprecated Replaced with {@link #awaitUninterruptibly()}.
     */
    @Deprecated
    void join();

    /**
     * @deprecated Replaced with {@link #awaitUninterruptibly(long)}.
     */
    @Deprecated
    boolean join(long timeoutMillis);

    /**
     * Returns if the asynchronous operation is completed.
     */
    boolean isDone();

    /**
     * Adds an event <tt>listener</tt> which is notified when
     * this future is completed. If the listener is added
     * after the completion, the listener is directly notified.
     */
    IoFuture addListener(IoFutureListener<?> listener);

    /**
     * Removes an existing event <tt>listener</tt> so it won't be notified when
     * the future is completed.
     */
    IoFuture removeListener(IoFutureListener<?> listener);
}


DefaultIoFuture  实现了IoFuture 接口。

IoFuture Represents the completion of an asynchronous I/O operation on an IoSession .

IoFuture接口表示异步Io操作的完成。同时提供addListener 、removeListener 监听器的功能。当IoFuture 操作完成时,会调用IoFutureListener 的方法。



public interface IoFuture {
    /**
     * Returns the {@link IoSession} which is associated with this future.
     */
    IoSession getSession();

    /**
     * Wait for the asynchronous operation to complete.
     * The attached listeners will be notified when the operation is 
     * completed.
     */
    IoFuture await() throws InterruptedException;

    /**
     * Wait for the asynchronous operation to complete with the specified timeout.
     *
     * @return <tt>true</tt> if the operation is completed.
     */
    boolean await(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * Wait for the asynchronous operation to complete with the specified timeout.
     *
     * @return <tt>true</tt> if the operation is completed.
     */
    boolean await(long timeoutMillis) throws InterruptedException;

    /**
     * Wait for the asynchronous operation to complete uninterruptibly.
     * The attached listeners will be notified when the operation is 
     * completed.
     * 
     * @return the current IoFuture
     */
    IoFuture awaitUninterruptibly();

    /**
     * Wait for the asynchronous operation to complete with the specified timeout
     * uninterruptibly.
     *
     * @return <tt>true</tt> if the operation is completed.
     */
    boolean awaitUninterruptibly(long timeout, TimeUnit unit);

    /**
     * Wait for the asynchronous operation to complete with the specified timeout
     * uninterruptibly.
     *
     * @return <tt>true</tt> if the operation is finished.
     */
    boolean awaitUninterruptibly(long timeoutMillis);

    /**
     * @deprecated Replaced with {@link #awaitUninterruptibly()}.
     */
    @Deprecated
    void join();

    /**
     * @deprecated Replaced with {@link #awaitUninterruptibly(long)}.
     */
    @Deprecated
    boolean join(long timeoutMillis);

    /**
     * Returns if the asynchronous operation is completed.
     */
    boolean isDone();

    /**
     * Adds an event <tt>listener</tt> which is notified when
     * this future is completed. If the listener is added
     * after the completion, the listener is directly notified.
     */
    IoFuture addListener(IoFutureListener<?> listener);

    /**
     * Removes an existing event <tt>listener</tt> so it won't be notified when
     * the future is completed.
     */
    IoFuture removeListener(IoFutureListener<?> listener);
}



public class DefaultIoFuture implements IoFuture {


    /** A number of seconds to wait between two deadlock controls ( 5 seconds ) */
    private static final long DEAD_LOCK_CHECK_INTERVAL = 5000L;


    /** The associated session */
    private final IoSession session;
 
   
    /** A lock used by the wait() method */
    private final Object lock;


    private IoFutureListener<?> firstListener;


    private List<IoFutureListener<?>> otherListeners;

    //异步操作的结果
    private Object result;
    //异步操作是否完成
    private boolean ready;

   //当前等待异步操作的线程数量
    private int waiters;


    /**
     * Creates a new instance associated with an {@link IoSession}.
     *
     * @param session an {@link IoSession} which is associated with this future
     */
    public DefaultIoFuture(IoSession session) {
        this.session = session;
        this.lock = this;
    }



   //调用await0()方法,将会同步等待异步操作的完成。
    /**
     * Wait for the Future to be ready. If the requested delay is 0 or
     * negative, this method immediately returns the value of the
     * 'ready' flag.
     * Every 5 second, the wait will be suspended to be able to check if
     * there is a deadlock or not.
     * 
     * @param timeoutMillis The delay we will wait for the Future to be ready
     * @param interruptable Tells if the wait can be interrupted or not
     * @return <code>true</code> if the Future is ready
     * @throws InterruptedException If the thread has been interrupted
     * when it's not allowed.
     */
    private boolean await0(long timeoutMillis, boolean interruptable) throws InterruptedException {
        long endTime = System.currentTimeMillis() + timeoutMillis;


        if (endTime < 0) {
            endTime = Long.MAX_VALUE;
        }


        synchronized (lock) {
            if (ready) {
                return ready;
            } else if (timeoutMillis <= 0) {
                return ready;
            }


            waiters++;


            try {
                for (;;) {
                    try {
                        long timeOut = Math.min(timeoutMillis, DEAD_LOCK_CHECK_INTERVAL);
                        lock.wait(timeOut);
                    } catch (InterruptedException e) {
                        if (interruptable) {
                            throw e;
                        }
                    }


                    if (ready) {
                        return true;
                    }


                    if (endTime < System.currentTimeMillis()) {
                        return ready;
                    }
                }
            } finally {
                waiters--;
                if (!ready) {
                    checkDeadLock();
                }
            }
        }
    }


   //当IoFuture 事件完成时, 调用setValue() 设置IoFuture异步计算的结果,并通过notifyListeners()方法来完成监听器的调用

    /**
     * Sets the result of the asynchronous operation, and mark it as finished.
     */
    public void setValue(Object newValue) {
        synchronized (lock) {
            // Allow only once.
            if (ready) {
                return;
            }


            result = newValue;
            ready = true;
            if (waiters > 0) {
                lock.notifyAll();
            }
        }


        notifyListeners();
    }


    public IoFuture addListener(IoFutureListener<?> listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener");
        }


        boolean notifyNow = false;
        synchronized (lock) {
            if (ready) {
                notifyNow = true;
            } else {
                if (firstListener == null) {
                    firstListener = listener;
                } else {
                    if (otherListeners == null) {
                        otherListeners = new ArrayList<IoFutureListener<?>>(1);
                    }
                    otherListeners.add(listener);
                }
            }
        }


        if (notifyNow) {
            notifyListener(listener);
        }
        return this;
    }


    /**
     * {@inheritDoc}
     */
    public IoFuture removeListener(IoFutureListener<?> listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener");
        }


        synchronized (lock) {
            if (!ready) {
                if (listener == firstListener) {
                    if (otherListeners != null && !otherListeners.isEmpty()) {
                        firstListener = otherListeners.remove(0);
                    } else {
                        firstListener = null;
                    }
                } else if (otherListeners != null) {
                    otherListeners.remove(listener);
                }
            }
        }


        return this;
    }


    private void notifyListeners() {
        // There won't be any visibility problem or concurrent modification
        // because 'ready' flag will be checked against both addListener and
        // removeListener calls.
        if (firstListener != null) {
            notifyListener(firstListener);
            firstListener = null;


            if (otherListeners != null) {
                for (IoFutureListener<?> l : otherListeners) {
                    notifyListener(l);
                }
                otherListeners = null;
            }
        }
    }

}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值