首先不得不說這個類org.apache.tomcat.util.net.JIoEndpoint,它負責所有的TCP請求連接,實現了一個服務器模式,啟用一個后臺監聽線程,負責接收到來的socket,然后從線程池中取出響應的worker,扔給worker進行處理,自己繼續監聽。其次worker是一個負責處理socket的一個線程,就是它帶著用戶的請求開始進入Tomcat世界的,默認的worker總共有200個,即:最多200個線程。當處理完一個請求的時候,這個線程并不會銷毀,而是進入wait阻塞,這個線程的對象也不會銷毀,是進入了一個棧里面,對應workstack那個數據結構。每當接收線程拿到一個socket的時候,就先從棧里面拿出一個已有的線程對象,然后就利用該對象的assign方法,將這個socket給它,并調用notify重新喚醒這個worker的處理線程。以后我們做小型服務器的時候,可以借鑒它的實現方式。正在研究多線程的朋友,這個類絕對讓你可以學的透徹!
相對應的還有一個org.apache.tomcat.util.net.NioEndpoint,這個和前面那個功能差不多,但是用了NIO包里的API,有一個最大的區別就是,接收線程接收一個socket之后,可能會將這個socket先放入緩存池,然后worker從池里面拿socket去處理,比前面那個類看起來功能和性能都會提升很多,不過代碼行有2K多,相當復雜,設計不夠精巧,有興趣可以去研究下。
org.apache.tomcat.util.buf.MessageBytes:這是一個接近底層的字符串處理類,為什么說是接近底層,是因為socket接收進來的都是字節類型,而java用的是char或者String,這之間的轉換涉及到編碼問題和性能問題,所以凡是socket收進來的信息,全部都用這個類表示,只有當要輸出字符串的時候,才會將里面的字節進行轉換,實現一種延遲加載的懶模式,被Tomcat底層所使用的Request類,就是大量使用了這個類來存放數據。我們來小小窺視一下,Request類:
- private MessageBytes methodMB = MessageBytes.newInstance();
- private MessageBytes unparsedURIMB = MessageBytes.newInstance();
- private MessageBytes uriMB = MessageBytes.newInstance();
- private MessageBytes decodedUriMB = MessageBytes.newInstance();
- private MessageBytes queryMB = MessageBytes.newInstance();
- private MessageBytes protoMB = MessageBytes.newInstance();
- // remote address/host
- private MessageBytes remoteAddrMB = MessageBytes.newInstance();
- private MessageBytes localNameMB = MessageBytes.newInstance();
- private MessageBytes remoteHostMB = MessageBytes.newInstance();
- private MessageBytes localAddrMB = MessageBytes.newInstance();
- private MimeHeaders headers = new MimeHeaders();
或許大家會覺得,構造出這么多的類,性能會高到哪里去,其實不是這樣的,不停的構造和銷毀對象的確會損耗相當的性能,但是一個對象被構造出來,可以重復利用,那就相當完美了,這個類就是如此的設計,其中有一個回收資源的方法,叫recycle(),這個方法可以清空里面的數組,清空里面的對象,而不會銷毀自己本身,因為使用它的對象,只要調用recycle,以后又可以重復使用了。
MessageBytes其實內置了2個重要的類,org.apache.tomcat.util.buf.ByteChunk和org.apache.tomcat.util.buf.CharChunk,這2個類帶我們回到了C時代,為什么這么說?因為它簡直就是一個字符串處理類,一些眼熟的算法全部映入眼簾,比如字符轉匹配算法,indexOf,startsWith,判斷字符轉是否相等,查找字符,等等,比之JDK提供的性能更好,功能更強大(這句話說過了,呵呵)
還有一個實用的值得學習的數據結構是,org.apache.tomcat.util.buf.Ascii,如果知道表驅動的朋友們,一定對這個類很熟悉了,判斷大小寫?判斷是不是英文單詞?判斷是不是空白符?判斷是不是數字,將字節類型轉換為int、long類型,大小寫轉換,等等。這些都是大學計算機課程的課后練習題