簡體   English   中英

為什么我要避免在servlet中使用InheritableThreadLocal?

[英]Why should I avoid using InheritableThreadLocal in servlets?

我在Servlet類中使用了InheritableThreadLocal 因此它可以從它的子線程中獲得。 在線程池執行程序中使用InheritableThreadLocal是邪惡的嗎? 比如servlet線程池。

我的問題。

1)為什么我們要避免在servlets中使用InheritableThreadLocals

2)在InheritableThreadLocal是否可以進行內存泄漏?

3) InheritableThreadLocal還有其他選擇嗎?

4)如果線程將被重用會發生什么, threadlocal存儲的值將不會被清除?

我的實時場景

public class UserAccessFilter implements javax.servlet.Filter {

      static final InheritableThreadLocal<String> currentRequestURI = new InheritableThreadLocal<String>();

      public void  doFilter(ServletRequest req, ServletResponse resp , FilterChain fc) throws IOException, ServletException{
              String uri = request.getRequestURI();
              fc.doFilter(request, response);         
      }
}


public class MailServlet extends HttpServlet{

      @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String mailCount = req.getParameter("mailCount");

    if(mailCount != null && !"".equals(mailCount) && mailCount.matches("[0-9]+")){
        MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount))); //NO I18N
        Thread t = new Thread(mailThread);
        t.start();
    }

    resp.getWriter().println("Mail Servlet.............."); //NO I18N

}              

}

class MailThread implements Runnable{

private String from;
private String to;

public MailThread(String from , String to){
    this.from = from;
    this.to = to;
}


@Override
public void run() {
    sendMail();
}

    public void sendMail(){
        //I want this uri from child threads. I can't pass this value to this constructor.
        String uri = currentRequestURI.get();
        //Do Mail Operations
    }


}

過濾器 - > Servlet A - >子線程--->郵件線程(這里我得到過濾器中設置的值)。

為什么我們要避免在servlet中使用InheritableThreadLocals?

它們代表了將信息從一個請求泄漏到另一個請求的潛在途徑。 “問題”是請求由線程池處理。 當請求完成時,線程處理的下一個請求可能是針對不同的用戶。 但是如果你在完成第一個請求時忘記清除線程本地狀態,那么第二個請求可能會使用它。

InheritableThreadLocal中是否存在內存泄漏?

是的......有點兒。 如果我們假設工作池是有界的,則任何線程的線程本地狀態都可能被覆蓋,從而清除內存泄漏。 在最壞的情況下,問題是有限的內存泄漏......受池中線程數量的限制。

信息泄漏問題更令人擔憂。

是否有任何替代InheritableThreadLocal?

在請求或響應對象中設置屬性更好。

如果線程將被重用會發生什么,threadlocal中存儲的值將不會被清除。

它不會被清除。 那就是問題所在!

您的示例有效, MailThread在創建時繼承 currentRequestURI的值。

UserAccessFilterjava.lang.InheritableThreadLocal只是混淆了代碼試圖做的事情,這是邪惡的部分。

更改MailThread的構造函數有什么問題,以便您可以從MailServlet傳遞請求URI,如下所示:

MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount)), req.getRequestURI());

那么你不需要本地的線程,你不需要過濾器,代碼更清晰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM