Tomcat源码分析(三)------ 可携带状态的线程池
最近想实现一个可携带状态的线程池,具体需求就是池中的线程被用来处理某种信息,而此信息可视为线程所依赖的外部状态。如果用简单的线程池来实现,线程初始化时就得赋予某些信息,使得线程无法被再次利用。在看老版Tomcat的源码时,找到了答案,其实现思路主要是利用了线程的等待和唤起,HttpProcessor的实现正好基于此思路,时序图如下所示:
初始化HttpProcessor线程时,没法赋予所需的Socket对象,因为如果在初始化阶段就赋予Socket会导致此线程没法回收用来处理其他Socket。因此,在HttpProcessor的run阶段,先把线程给wait住,具体在await方法里体现,代码如下所示:
- /**
- *AwaitanewlyassignedSocketfromourConnector,or<code>null</code>
- *ifwearesupposedtoshutdown.
- */
- privatesynchronizedSocketawait(){
- //WaitfortheConnectortoprovideanewSocket
- while(!available){
- try{
- wait();
- }catch(InterruptedExceptione){
- }
- }
- //NotifytheConnectorthatwehavereceivedthisSocket
- Socketsocket=this.socket;
- available=false;
- notifyAll();
- if((debug>=1)&&(socket!=null))
- log("Theincomingrequesthasbeenawaited");
- return(socket);
- }
当HttpConnector调用HttpProcessor.assign(socket)方法时,会给此线程赋予Socket对象,并唤起此线程,使其继续执行,assign方法的源码如下所示:
- /**
- *ProcessanincomingTCP/IPconnectiononthespecifiedsocket.Any
- *exceptionthatoccursduringprocessingmustbeloggedandswallowed.
- *<b>NOTE</b>:ThismethodiscalledfromourConnector'sthread.We
- *mustassignittoourownthreadsothatmultiplesimultaneous
- *requestscanbehandled.
- *
- *@paramsocketTCPsockettoprocess
- */
- synchronizedvoidassign(Socketsocket){
- //WaitfortheProcessortogetthepreviousSocket
- while(available){
- try{
- wait();
- }catch(InterruptedExceptione){
- }
- }
- //StorethenewlyavailableSocketandnotifyourthread
- this.socket=socket;
- available=true;
- notifyAll();
- if((debug>=1)&&(socket!=null))
- log("Anincomingrequestisbeingassigned");
- }
线程被唤起和赋予socket对象后,继续执行核心的process方法,HttpProcessor.run的完整源码如下所示:
- /**
- *ThebackgroundthreadthatlistensforincomingTCP/IPconnectionsand
- *handsthemofftoanappropriateprocessor.
- */
- publicvoidrun(){
- //Processrequestsuntilwereceiveashutdownsignal
- while(!stopped){
- //Waitforthenextsockettobeassigned
- Socketsocket=await();
- if(socket==null)
- continue;
- //Processtherequestfromthissocket
- try{
- process(socket);
- }catch(Throwablet){
- log("process.invoke",t);
- }
- //Finishupthisrequest
- connector.recycle(this);
- }
- //TellthreadStop()wehaveshutourselvesdownsuccessfully
- synchronized(threadSync){
- threadSync.notifyAll();
- }
- }