2013-01-24 42 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中创建线程之后,该值将被继承,之后它可以被设置为请求线程所需的任何值,看到的创建线程的值将不受影响。 –

相关问题