Tomcat源码分析(三)------ 可携带状态的线程池

来源:互联网 发布:好看电影推荐 知乎 编辑:程序博客网 时间:2024/06/11 13:27

摘自http://blog.csdn.net/cutesource/article/details/5081916

最近想实现一个可携带状态的线程池,具体需求就是池中的线程被用来处理某种信息,而此信息可视为线程所依赖的外部状态。如果用简单的线程池来实现,线程初始化时就得赋予某些信息,使得线程无法被再次利用。在看老版Tomcat的源码时,找到了答案,其实现思路主要是利用了线程的等待和唤起,HttpProcessor的实现正好基于此思路,时序图如下所示:

初始化HttpProcessor线程时,没法赋予所需的Socket对象,因为如果在初始化阶段就赋予Socket会导致此线程没法回收用来处理其他Socket。因此,在HttpProcessor的run阶段,先把线程给wait住,具体在await方法里体现,代码如下所示:

[java] view plaincopy
  1. /** 
  2.  * Await a newly assigned Socket from our Connector, or <code>null</code> 
  3.  * if we are supposed to shut down. 
  4.  */  
  5. private synchronized Socket await() {  
  6.   
  7.     // Wait for the Connector to provide a new Socket  
  8.     while (!available) {  
  9.         try {  
  10.             wait();  
  11.         } catch (InterruptedException e) {  
  12.         }  
  13.     }  
  14.   
  15.     // Notify the Connector that we have received this Socket  
  16.     Socket socket = this.socket;  
  17.     available = false;  
  18.     notifyAll();  
  19.   
  20.     if ((debug >= 1) && (socket != null))  
  21.         log("  The incoming request has been awaited");  
  22.   
  23.     return (socket);  
  24.   
  25. }  

当HttpConnector调用HttpProcessor.assign(socket)方法时,会给此线程赋予Socket对象,并唤起此线程,使其继续执行,assign方法的源码如下所示:

[java] view plaincopy
  1. /** 
  2.  * Process an incoming TCP/IP connection on the specified socket.  Any 
  3.  * exception that occurs during processing must be logged and swallowed. 
  4.  * <b>NOTE</b>:  This method is called from our Connector's thread.  We 
  5.  * must assign it to our own thread so that multiple simultaneous 
  6.  * requests can be handled. 
  7.  * 
  8.  * @param socket TCP socket to process 
  9.  */  
  10. synchronized void assign(Socket socket) {  
  11.   
  12.     // Wait for the Processor to get the previous Socket  
  13.     while (available) {  
  14.         try {  
  15.             wait();  
  16.         } catch (InterruptedException e) {  
  17.         }  
  18.     }  
  19.   
  20.     // Store the newly available Socket and notify our thread  
  21.     this.socket = socket;  
  22.     available = true;  
  23.     notifyAll();  
  24.   
  25.     if ((debug >= 1) && (socket != null))  
  26.         log(" An incoming request is being assigned");  
  27.   
  28. }  

线程被唤起和赋予socket对象后,继续执行核心的process方法,HttpProcessor.run的完整源码如下所示:

[java] view plaincopy
  1. /** 
  2.  * The background thread that listens for incoming TCP/IP connections and 
  3.  * hands them off to an appropriate processor. 
  4.  */  
  5. public void run() {  
  6.   
  7.     // Process requests until we receive a shutdown signal  
  8.     while (!stopped) {  
  9.   
  10.         // Wait for the next socket to be assigned  
  11.         Socket socket = await();  
  12.         if (socket == null)  
  13.             continue;  
  14.   
  15.         // Process the request from this socket  
  16.         try {  
  17.             process(socket);  
  18.         } catch (Throwable t) {  
  19.             log("process.invoke", t);  
  20.         }  
  21.   
  22.         // Finish up this request  
  23.         connector.recycle(this);  
  24.   
  25.     }  
  26.   
  27.     // Tell threadStop() we have shut ourselves down successfully  
  28.     synchronized (threadSync) {  
  29.         threadSync.notifyAll();  
  30.     }  
  31.   
  32. }  


0 0