天天看點

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()) {

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

 }

本文轉自Phinecos(洞庭散人)部落格園部落格,原文連結http://www.cnblogs.com/phinecos/archive/2008/12/04/1347394.html,如需轉載請自行聯系原作者