高併發程式設計thirft原始碼解析
我用的thrift模式:
網路程式設計模式
arg.selectorThreads(Integer.parseInt(mProp.get("LogServerSelectorThread").toString()));
這步驟是啟動了多個執行緒,每個執行緒裡面有個bocking queue佇列,佇列元素是socketchannel,執行緒啟動後就不斷消費這個佇列
並不是select使用了多執行緒,而是便利selectkey時,沒當有一個連線socketchannel進來就加入佇列,
arg.workerThreads(Integer.parseInt(mProp.get("LogServerWorkThread").toString())); //worker執行緒數
這一步其實是處理selector的連線數,內部使用了ExcuteService這個執行緒池,
每天有個連線進來,就是用從這個執行緒池裡面任意取一個執行緒來執行下面這個方法,目的是分別client到一個指定SelectorThread執行緒裡面
invoker.submit(new Runnable() { public void run() { doAddAccept(targetThread, client); } });
問題1: 為什麼這裡使用了兩個多執行緒,為什麼不用一個就夠了呢?
我的分析是:
1、如果用一個執行緒池,那麼不斷有連線進來,就會不斷生成一個執行緒處理,
每個執行緒都要處理完這些資料才會釋放,那麼併發高度時候,就會有大量的處理執行緒積壓,
這個執行緒池就會不斷膨脹,最終崩潰
2、如果每個執行緒內部採用一個佇列,那就要分別啟動這些執行緒,並加入socketchannel到這個佇列裡面
thirft排程策略有:FAIR_ACCEPT和FAST_ACCEPT,預設是後者,
就是說FAST_ACCEPT模式其實就是答案裡說的,只是用了一個執行緒池模式,沒有用ExcuteServcie
問題2: SelectorThread內部為什麼用blocking queue,而不用concurrent queue呢?
因為這個queue不需要共享,blocking queue效率更快