2013-01-24 40 views
4

我在我的Servlet類中使用了InheritableThreadLocal。以便它可以從它的子線程中獲得。在線程池執行程序中使用InheritableThreadLocal是否是這種罪惡? 。比如servlet線程池。爲什麼我應該避免在servlet中使用InheritableThreadLocal?

我的問題。

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("[email protected]", 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 - >子線程--->郵件線程(在這裏我得到的過濾器設置好的值)。

回答

0

您的示例工程MailThread在創建時繼承的值currentRequestURI

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

有什麼不對改變MailThread構造,這樣就可以從MailServlet這樣傳遞請求URI:

MailThread mailThread = new MailThread("[email protected]", generateToAddress(Integer.parseInt(mailCount)), req.getRequestURI()); 

那麼你有沒有需要一個線程本地的,你不需要過濾器和代碼更清晰。

+0

我無法將requestURI傳遞給'MailThread'。在這裏我發佈示例場景。 – kannanrbk

+0

爲什麼你可以將requestURI傳遞給'MailThread',在'doGet'方法中有'HttpServletRequest'? –

+0

是的,但我不能限制發送請求的uri發送電子郵件。它可以被其他成員使用。 – kannanrbk

8

爲什麼我們應該避免在servlet中使用InheritableThreadLocals?

它們代表從一個請求到另一個請求泄漏信息的潛在路徑。 「問題」是請求由線程池處理。當請求完成時,線程處理的下一個請求很可能是針對不同的用戶。但是,如果您在完成第一個請求時忘記清除線程本地狀態,則可能會由第二個請求使用該線程。

InheritedThreadLocal中是否存在內存泄漏?

是......有點。如果我們假定工作池是有界的,任何線程的線程本地狀態可能會被覆蓋,清除內存泄漏。最糟糕的問題是一個有限的內存泄漏......受到池中線程數的限制。

信息泄漏問題更關注。

InheritableThreadLocal是否有其他選擇?

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

如果線程將被重新使用,存儲在threadlocal中的值將不會被清除。

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

+1

我正在重置'filter'上的值,那麼這不是問題? – kannanrbk

+0

這取決於何時該值被重置......以及您是否可以保證它將總是被重置。 –

+0

'UserAccessFilter'中是否沒有一行應該設置值?然後,當在servlet中創建線程之後,該值將被繼承,之後它可以被設置爲請求線程所需的任何值,看到的創建線程的值將不受影響。 –

相關問題