Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Servlet 3规范和ThreadLocal_Java_Multithreading_Servlets_Thread Local_Servlet 3.0 - Fatal编程技术网

Java Servlet 3规范和ThreadLocal

Java Servlet 3规范和ThreadLocal,java,multithreading,servlets,thread-local,servlet-3.0,Java,Multithreading,Servlets,Thread Local,Servlet 3.0,据我所知,Servlet3规范引入了异步处理特性。除此之外,这将意味着同一线程可以并且将被重新用于处理另一个并发HTTP请求。这不是革命性的,至少对以前与NIO合作过的人来说是这样 无论如何,这导致了另一件重要的事情:noThreadLocalvariables作为请求数据的临时存储。因为如果同一个线程突然成为不同HTTP请求的载体线程,请求本地数据将暴露给另一个请求 所有这些都是我基于阅读文章的纯推测,我没有时间玩任何Servlet3实现(Tomcat7、GlassFish 3.0.X等) 因

据我所知,Servlet3规范引入了异步处理特性。除此之外,这将意味着同一线程可以并且将被重新用于处理另一个并发HTTP请求。这不是革命性的,至少对以前与NIO合作过的人来说是这样

无论如何,这导致了另一件重要的事情:no
ThreadLocal
variables
作为请求数据的临时存储。因为如果同一个线程突然成为不同HTTP请求的载体线程,请求本地数据将暴露给另一个请求

所有这些都是我基于阅读文章的纯推测,我没有时间玩任何Servlet3实现(Tomcat7、GlassFish 3.0.X等)

因此,问题是:

  • 我假设
    ThreadLocal
    将不再是保存请求数据的方便黑客,对吗
  • 有没有人玩过Servlet 3实现中的任何一个并尝试使用
    ThreadLocal
    s来证明上述内容
  • 除了在HTTP会话中存储数据外,还有其他类似的易于接触的黑客吗
编辑:别误会我。我完全理解作为一名黑客的危险和
ThreadLocal
。事实上,我总是建议不要在类似的情况下使用它。然而,信不信由你,线程上下文的使用频率远远超过了你的想象。Spring的
OpenSessionInViewFilter
就是一个很好的例子,根据其Javadoc:

此筛选器生成Hibernate会话 可通过当前线程访问, 它将被自动检测到 事务管理器

这不是严格意义上的
ThreadLocal
(尚未检查源代码),但听起来已经很令人担忧了。我可以想到更多类似的场景,而丰富的web框架使得这种情况更可能发生

简单地说,许多人已经在这个黑客之上建造了他们的沙堡,不管有没有意识到。因此,斯蒂芬的回答是可以理解的,但不完全是我想要的。我想确认是否有人真正尝试过,并且能够重现失败的行为,因此这个问题可以作为被同样问题困住的其他人的参考点。

(注意:我还没有详细阅读Servlet 3规范,所以我不能肯定该规范说明了您认为它的功能。我只是假设它确实如此……)

我认为ThreadLocal将不再是保存请求数据的方便黑客,对吗

使用
ThreadLocal
始终是一种糟糕的方法,因为当工作线程完成一个请求并启动另一个请求时,您总是有信息泄漏的风险。将内容作为属性存储在
ServletRequest
对象中总是一个更好的主意

现在你有了另一个理由,可以用“正确”的方式来做

有没有人玩过Servlet3实现中的任何一个,并尝试使用ThreadLocals来证明上述内容

这不是正确的方法。它只告诉您在测试的特定环境下特定实现的特定行为。您不能概括

正确的方法是假设它有时会发生,如果规范说它可以……并设计你的webapp来考虑它

(不用担心!显然,在这种情况下,默认情况下不会发生这种情况。您的webapp必须显式启用异步处理功能。如果您的代码中充斥着线程局部变量,建议您不要这样做…)

除了在HTTP会话中存储数据外,还有其他类似的易于接触的黑客吗


不正确。唯一正确的答案是将特定于请求的数据存储在ServletRequest或ServletResponse对象中。即使将其存储在HTTP会话中也可能是错误的,因为对于给定会话,可能会有多个请求同时处于活动状态。

除非您明确要求异步处理,否则异步处理不会打扰您

例如,如果servlet或请求的筛选器链中的任何筛选器未标记为
true
,则无法使请求异步。因此,您仍然可以对常规请求使用常规做法


当然,如果您确实需要异步处理,那么您需要使用适当的实践。基本上,当异步处理请求时,其处理被分为多个部分。这些部分不共享线程本地状态,但是,您仍然可以在每个部分内使用线程本地状态,尽管您必须在这两个部分之间手动管理状态n零件。

注意:黑客攻击随之而来。小心使用,或者干脆不要使用

只要您继续了解代码在哪个线程中执行,就没有理由不能安全地使用ThreadLocal

try {
    tl.set(value);
    doStuffUsingThreadLocal();
} finally {
    tl.remove();
}
这并不是说你的调用堆栈是随机切换的。见鬼,如果你想在调用堆栈的深处设置ThreadLocal值,然后再进一步使用,你也可以破解它:

public class Nasty {

    static ThreadLocal<Set<ThreadLocal<?>>> cleanMe = 
        new ThreadLocal<Set<ThreadLocal<?>>>() {
            protected Set<ThreadLocal<?>> initialValue() {
                return new HashSet<ThreadLocal<?>>();
            }
        };

    static void register(ThreadLocal<?> toClean) {
       cleanMe.get().add(toClean);
    }

    static void cleanup()  {
        for(ThreadLocal<?> tl : toClean)
            tl.remove();
        toClean.clear();
    }
}
公共类{
静态线程本地>>(){
受保护集>();
}
};
静态无效寄存器(ThreadLocal toClean){
cleanMe.get().add(toClean);
}
静态空洞清理(){
用于(ThreadLocal tl:toClean)
tl.删除();
toClean.clear();
}
}

然后在设置ThreadLocals时注册ThreadLocals,并在某个地方的finally子句中进行清理。这都是可耻的恶意行为,您可能不应该这么做。很抱歉,我写了它,但为时已晚://

我仍然想知道为什么人们会使用腐烂的javax.servlet API来实际实现他们的servlet。我所做的是:

  • 我有一个基类
    HttpRequestHandler
    ,它有请求、响应的私有字段,还有一个
    handle()
    方法,可以向ge抛出异常和一些实用方法