[英]Why should I avoid using InheritableThreadLocal in servlets?
I am using InheritableThreadLocal
in my Servlet
Class. 我在
Servlet
类中使用了InheritableThreadLocal
。 So that It will available from it's child threads. 因此它可以从它的子线程中获得。 Is that evil using
InheritableThreadLocal
in thread pool executors? 在线程池执行程序中使用
InheritableThreadLocal
是邪恶的吗? . 。 Such as servlet thread pool.
比如servlet线程池。
My Questions. 我的问题。
1) Why should we avoid using InheritableThreadLocals
in servlets? 1)为什么我们要避免在servlets中使用
InheritableThreadLocals
?
2) Is this memory leak possible in InheritableThreadLocal
? 2)在
InheritableThreadLocal
是否可以进行内存泄漏?
3) Is there any alternative for InheritableThreadLocal
?. 3)
InheritableThreadLocal
还有其他选择吗?
4) What happens if the thread will be reused , the value stored in threadlocal
will not be cleared? 4)如果线程将被重用会发生什么,
threadlocal
存储的值将不会被清除?
My Real Time Scenario 我的实时场景
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
}
}
Filter --> Servlet A --> Child Thread ---> Mail Thread (Here I am getting the value setted in filter) . 过滤器 - > Servlet A - >子线程--->邮件线程(这里我得到过滤器中设置的值)。
Why should we avoid using InheritableThreadLocals in servlets?
为什么我们要避免在servlet中使用InheritableThreadLocals?
They represent a potential path for leaking information from one request to another. 它们代表了将信息从一个请求泄漏到另一个请求的潜在途径。 The "problem" is that requests are handled by a pool of threads.
“问题”是请求由线程池处理。 When on request is completed, the next request that a thread handles is likely to be for a different user.
当请求完成时,线程处理的下一个请求可能是针对不同的用户。 But if you forget to clear the thread local state on finishing the first request, there is a potential that it might be used by the second one.
但是如果你在完成第一个请求时忘记清除线程本地状态,那么第二个请求可能会使用它。
Is a memory leak possible in InheritableThreadLocal?
InheritableThreadLocal中是否存在内存泄漏?
Yes ... sort of. 是的......有点儿。 If we assume that the worker pool is bounded, the thread local state of any thread is likely to be overwritten, clearing the memory leak.
如果我们假设工作池是有界的,则任何线程的线程本地状态都可能被覆盖,从而清除内存泄漏。 At worst the problem is a bounded memory leak ... bounded by the number of threads in the pool.
在最坏的情况下,问题是有限的内存泄漏......受池中线程数量的限制。
The information leakage problem is more concerning. 信息泄漏问题更令人担忧。
Is there any alternative for InheritableThreadLocal?
是否有任何替代InheritableThreadLocal?
Setting attributes in the request or response object is better. 在请求或响应对象中设置属性更好。
What happens if the thread will be reused, the value stored in threadlocal will not be cleared.
如果线程将被重用会发生什么,threadlocal中存储的值将不会被清除。
It won't be cleared. 它不会被清除。 THAT is the problem!
那就是问题所在!
Your example works, the MailThread
inherits the value of currentRequestURI
when it is created. 您的示例有效,
MailThread
在创建时继承 currentRequestURI
的值。
But the UserAccessFilter
and the java.lang.InheritableThreadLocal
just serve to confuse what the code is trying to do, which is the evil part. 但
UserAccessFilter
和java.lang.InheritableThreadLocal
只是混淆了代码试图做的事情,这是邪恶的部分。
What's wrong changing the constructor of MailThread
so that you can pass the request URI from the MailServlet
like this: 更改
MailThread
的构造函数有什么问题,以便您可以从MailServlet
传递请求URI,如下所示:
MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount)), req.getRequestURI());
Then you have no need for a thread local, you don't need the filter and the code is clearer. 那么你不需要本地的线程,你不需要过滤器,代码更清晰。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.