自己动手写一个tomcat之3池化processor

发布时间:2026/8/15 11:02:54
自己动手写一个tomcat之3池化processor 写在前面源码 。本文来池化processor以提高服务处理性能。同时也会将processor改造为线程异步执行这样可以不用阻塞连接器connector的执行过程进一步提高程序性能。1正文首先将processor改造为线程也很简单只需要实现java.lang.Runnable接口即可,具体改造如下packagemonitomcat.server;// ...publicclassHttpProcessorimplementsRunnable{Socketsocket;booleanavailablefalse;// 维护连接器对象池化使用HttpConnectorconnector;// ...Overridepublicvoidrun(){while(true){// Wait for the next socket to be assignedSocketsocketawait();if(socketnull)continue;// Process the request from this socketprocess(socket);// Finish up this request处理完毕归还处理器到dequeue中以备下次使用connector.recycle(this);}}publicvoidstart(){ThreadthreadnewThread(this);thread.start();}publicvoidprocess(Socketsocket){try{Thread.sleep(3000);}catch(InterruptedExceptione1){e1.printStackTrace();}InputStreaminputnull;OutputStreamoutputnull;try{// ...// Close the socket业务处理完毕关闭套接字socket.close();}catch(Exceptione){e.printStackTrace();}}synchronizedvoidassign(Socketsocket){System.out.println(HttpProcessor.assign...);// wait for the connector to provide a new Socketwhile(available){try{wait();}catch(InterruptedExceptione){}}// Store the newly available Socket and notify our threadthis.socketsocket;availabletrue;notifyAll();}privatesynchronizedSocketawait(){System.out.println(HttpProcessor.await...);// Wait for the Connector to provide a new Socketwhile(!available){try{wait();}catch(InterruptedExceptione){}}// Notify the Connector that we have received this SocketSocketsocketthis.socket;availablefalse;// notifyAll();return(socket);}}run方法阻塞在await()方法上等待socket进来。assign(Socket socket)方法用来分派socket将会唤醒阻塞在await方法上的processor异步线程执行业务处理具体看下连接器connector是如何池化以及启动processor线程分派任务的packagemonitomcat.server;importjava.io.IOException;importjava.net.InetAddress;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.ArrayDeque;importjava.util.Deque;publicclassHttpConnectorimplementsRunnable{intminProcessors3;intmaxProcessors10;// int minProcessors 1;// int maxProcessors 1;intcurProcessors0;DequeHttpProcessorprocessorsnewArrayDeque();publicvoidrun(){ServerSocketserverSocketnull;intport8080;try{serverSocketnewServerSocket(port,1,InetAddress.getByName(127.0.0.1));}catch(IOExceptione){e.printStackTrace();System.exit(1);}// initialize processors poolfor(inti0;iminProcessors;i){HttpProcessorinitprocessornewHttpProcessor(this);initprocessor.start();processors.push(initprocessor);}curProcessorsminProcessors;while(true){Socketsocketnull;try{socketserverSocket.accept();HttpProcessorprocessorcreateProcessor();if(processornull){socket.close();continue;}processor.assign(socket);// Close the socket// socket.close();}catch(Exceptione){e.printStackTrace();}}}publicvoidstart(){ThreadthreadnewThread(this);thread.start();}privateHttpProcessorcreateProcessor(){synchronized(processors){if(processors.size()0){// removes and returns the first element of this dequereturn((HttpProcessor)processors.pop());}if(curProcessorsmaxProcessors){return(((newProcessor())));}else{return(null);}}}privateHttpProcessornewProcessor(){HttpProcessorinitprocessornewHttpProcessor(this);initprocessor.start();processors.push(initprocessor);curProcessors;return((HttpProcessor)processors.pop());}voidrecycle(HttpProcessorprocessor){processors.push(processor);}}代码比较简单,看下即可这里说下processor线程池设置了最小值和最大值初始化时只初始最小值当不够用时直接new直到达到最大值这和jdk的线程池方案是不同的jdk的线程池方案时考虑到了线程创建成本高以及很快就会有可用线程两方面而将任务暂存到任务队列中只有在任务队列满时才会创建新的线程但是这种方案并不适合tomcat的场景因为暂存到任务队列的动作会降低程序执行的效率。这里要实现的是尽快执行每一个用户请求。启动服务所有的processor都会stand by准备处理socketConnected to the target VM, address: 127.0.0.1:53308, transport: socket HttpProcessor.await... HttpProcessor.await... HttpProcessor.await...如果有一个请求的话就会从processor池中取出一个并分配当前请求的socket给其处理并且处理完毕后继续进入下一个stand by2标准化request和response按照servlet规范request和response要实现javax.servlet.http.HttpServletRequest接口和javax.servlet.http.HttpServletResponse,如下定义HttpRequest类和HttpResponse类publicclassHttpRequestimplementsHttpServletRequest{}publicclassHttpResponseimplementsHttpServletResponse{}没有流程上的改变具体看代码吧源码 。写在后面参考文章列表手把手带你写一个 MiniTomcat 。