mina2 筆記

http://www.iteye.com/topic/1112123java

http://dongxuan.iteye.com/blog/901689服務器

http://scholers.iteye.com/blog/1452780多線程

 

基本流程性能

一、服務端監聽端口是否有鏈接創建,接收到請求,建立IoSessionspa

二、IoProcessor輪訓IO通道,處理IO操做(讀寫),從線程池調用IoHandler線程處理工做操作系統

三、IoHandler處理工做線程

幾個主要的概念
一、線程
Mina2中在三個地方使用了線程:netty

  • IoAcceptor/IoConnector線程

  IoAcceptor接收客戶端的鏈接創建,每監聽一個端口(調一次bind()方法)啓用一個線程;每接收到一次請求,建立一個IoSession對象,由於建立IoSession對象的速度足夠快,因此一個線程就夠了。code

    IoConnector用於與服務端創建鏈接,每鏈接一個服務器(調用一次connect()方法),建立一個IoSession對象。對象

  • IoProcessor線程

  真正執行IO操做的線程,默認啓用的線程數是CPU和核數+1,如單CPU雙核電腦,默認的IoProcessor就會建立3個,也就是說一個IoAcceptor/IoConnector會關聯一個    IoProcessor池,這個池中有3個IoProcessor。

  爲何IoProcessor比CPU核數大一?由於IO操做耗費資源。可是通常實現的時候都採用工做線程與IO線程分離,而且如今的CPU性能已經大大的提高了,因此能夠根據實際配置適當增長。如:netty中默認爲cpu個數*2+1。

  • IoHandler線程

  IoProcessor的構造方法有一個參數是java.util.concurrent.Executor,這個參數就是讓IO線程與工做線程分離的關鍵,也就是讓IoProcessor調用的IoHandler中的某些方法(MessageReceived()等)在線程池中分配的線程獨立運行,而不是在IoProcessor所在的線程。即:acceptor.getFilterChain().addLast(「threadpool」, new ExcetorFilter());這行代碼設置的若是不指定ExcetorFilter參數,默認使用OrderedThreadPoolExecutor

 

二、線程隊列

  OrderedThreadPoolExecutor等*Executor都是是繼承自ThreadPoolExecutor,區別在於隊列大小、隊列類型上。IoAcceptor實現NioSocketAcceptor默認用的是ExecutorService.newCachedThreadPool(),這是一個無界的線程池,而且隊列是一個同步隊列。

代碼以下:

public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }

ThreadPoolExecutor共有6個構造參數:

  corePoolSize:線程池維護線程的最少數量

  maximumPoolSize:線程池維護線程的最大數量

   keepAliveTime:線程池維護線程所容許的空閒時間

   unit:線程池維護線程所容許的空閒時間的單位

   workQueue:線程池所使用的緩衝隊列

    handler:線程池對拒絕任務的處理策略

排隊規則:

  A. 若是運行的線程少於corePoolSize,則Executor始終首選添加新的線程,而不進行排隊。

  B.  若是運行的線程等於或多於corePoolSize,則Executor始終首選將請求加入隊列,而不添加新的線程。

  C.  若是沒法將請求加入隊列,則建立新的線程,除非建立此線程超出maximumPoolSize,在這種狀況下,任務將被拒絕。

 

對於workQueue,排隊有三種通用策略:

  1. 直接提交工做隊列的默認選項是 SynchronousQueue,它將任務直接提交給線程而不保持它們。在此,若是不存在可用於當即運行任務的線程,即線程池已達到maximumPoolSizes,則試圖把任務加入隊列將失敗。此策略保證先來的請求先處理,能夠避免在處理可能具備內部依賴性的請求集時出現鎖。直接提交一般要求無界 maximumPoolSizes 以免拒絕新提交的任務。
  1. 無界隊列使用無界隊列將致使在全部 corePoolSize 線程都忙時新任務在隊列中等待。這樣,建立的線程就不會超過 corePoolSize。(結果是maximumPoolSize 的值無效了)。當每一個任務徹底獨立於其餘任務,即任務執行互不影響時,適合於使用無界隊列;例如,在 Web 頁服務器中。這種排隊可用於處理瞬態突發請求。
  1. 有界隊列當使用有限的 maximumPoolSizes 時,有界隊列(如 ArrayBlockingQueue)有助於防止資源耗盡,缺點是較難調整和控制,JDK並不推薦使用這種方式。隊列大小和最大池大小可能須要相互折衷:使用大型隊列和小型池能夠最大限度地下降 CPU 使用率、操做系統資源和上下文切換開銷,可是可能致使人工下降吞吐量。若是任務頻繁阻塞(例如,若是它們是 I/O 邊界),則系統可能爲超過您許可的更多線程安排時間。使用小型隊列一般要求較大的池大小,CPU 使用率較高,可是可能遇到不可接受的調度開銷,這樣也會下降吞吐量。
相關文章
相關標籤/搜索