ThreadPoolとThreadLoacal その2
Webコンテナ(少なくともTomcat5.0)でPoolされているThreadのThreadLocal.ThreadLocalMapってThreadが再利用されるたびにリフレクションとか使ってクリアーされているわけではないのですね。コードを読んでもわからないのでServlet動かしました。(はじめからこうすればよかった。)
なぜかクリアーされているはずだと思い込んでいましたがそうではありませんでした。気をつけねば。これは実装によってかわってくるんでしょうか。
ThreadLoacalを持つServlet
package hoge; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet extends HttpServlet { private static ThreadLocal threadLocal = new ThreadLocal(); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Object value = threadLocal.get(); System.out.println(Thread.currentThread().getName() + " : " + value); threadLocal.set("hoge"); } }
(何回かGetリクエストを実行して得た)出力結果。get()でnullが返ってくるのはThreadが初めて使われたときだけ。
http-8080-Processor4 : null http-8080-Processor4 : hoge http-8080-Processor4 : hoge http-8080-Processor4 : hoge http-8080-Processor3 : null http-8080-Processor3 : hoge http-8080-Processor3 : hoge http-8080-Processor3 : hoge http-8080-Processor3 : hoge http-8080-Processor4 : hoge http-8080-Processor3 : hoge http-8080-Processor3 : hoge
EclipseのDebugビューに表示されるスタック。コピれた。
org.apache.catalina.startup.Bootstrap at localhost:4152 System Thread [Finalizer] (Running) System Thread [Reference Handler] (Running) Thread [main] (Running) System Thread [Signal Dispatcher] (Running) Thread [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (Running) Thread [http-8080-Processor1] (Running) Thread [http-8080-Processor2] (Running) Thread [http-8080-Processor3] (Running) Thread [http-8080-Processor4] (Suspended (breakpoint at line 19 in MyServlet)) MyServlet.doGet(HttpServletRequest, HttpServletResponse) line: 19 MyServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 697 MyServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 810 ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 237 ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 157 StandardWrapperValve.invoke(Request, Response, ValveContext) line: 214 StandardValveContext.invokeNext(Request, Response) line: 104 StandardPipeline.invoke(Request, Response) line: 520 StandardContextValve.invokeInternal(Wrapper, Request, Response) line: 198 StandardContextValve.invoke(Request, Response, ValveContext) line: 152 StandardValveContext.invokeNext(Request, Response) line: 104 StandardPipeline.invoke(Request, Response) line: 520 StandardHostValve.invoke(Request, Response, ValveContext) line: 137 StandardValveContext.invokeNext(Request, Response) line: 104 ErrorReportValve.invoke(Request, Response, ValveContext) line: 117 StandardValveContext.invokeNext(Request, Response) line: 102 StandardPipeline.invoke(Request, Response) line: 520 StandardEngineValve.invoke(Request, Response, ValveContext) line: 109 StandardValveContext.invokeNext(Request, Response) line: 104 StandardPipeline.invoke(Request, Response) line: 520 StandardEngine(ContainerBase).invoke(Request, Response) line: 929 CoyoteAdapter.service(Request, Response) line: 160 Http11Processor.process(InputStream, OutputStream) line: 793 Http11Protocol$Http11ConnectionHandler.processConnection(TcpConnection, Object) line: 702 TcpWorkerThread.runIt(Object) line: 571 ThreadPool$ControlRunnable.run() line: 644 ThreadWithAttributes(Thread).run() line: 534 Thread [http-8080-Monitor] (Running) Thread [TP-Processor1] (Running) Thread [TP-Processor2] (Running) Thread [TP-Processor3] (Running) Thread [TP-Processor4] (Running) Thread [TP-Monitor] (Running)