在我的负载测试期间测试Tomcat NIO连接器时,才想到这一点。我使用了ThreadLocal的功能,另外我使用了Spring,我知道它在很多地方也使用了Spring。
由于NIO连接器每个连接没有线程,因此我担心,如果在清理之前与另一个线程共享ThreadLocal对象,可能会导致很难发现错误。但是,我认为这不是问题,因为它不是我可以找到的书面警告,也没有发现其他与此相关的警告。我假设NIO连接器对服务实际请求的线程没有影响。
在我接受这个假设之前,我希望找到一些具体的证据。
只有熟悉Tomcat代码的人才能为您提供具体的答案,但是我会尝试一个木制的:)
首先,您需要清楚是只使用NIO连接器还是在谈论异步servlet。在每种情况下,答案都会略有不同。
需要注意的主要事情是Java没有任何类型的延续,协同例程或线程重新安排。这意味着一旦启动在线程上运行的一段代码, 只有 那段 代码将在线程上运行,直到完成为止。
因此,如果您有:myObject.doSomething();那么doSomething就目前而言,它对该线程具有独占访问权。线程不会切换到其他代码- 不管您使用哪种类型的IO模型。
myObject.doSomething();
doSomething
可能(将会)发生的事情是,不同的线程将被调度为在不同的CPU上运行,但是每个线程将运行一段代码来完成。
所以如果doSomething是:
public static final ThreadLocal<MyClass> VALUE = new ThreadLocal<MyClass>(); public void doSomething() { VALUE.set(this); try { doSomethingElse(); } finally { VALUE.set(null); } }
那么就没有什么可担心的了- doSomethingElse将只运行一个线程,并且将在整个执行过程中将threadlocal设置为正确的值。
doSomethingElse
因此,简单的NIO连接器应该没有任何区别- 容器将service在servlet上调用方法,该servlet将在单个线程中执行,然后最后完成。只是容器在处理连接时能够以更有效的方式处理IO。
service
如果您使用的是异步servlet,则有所不同- 在这种情况下,您的servlet可能会针对单个请求多次调用(由于异步模型的工作方式),并且这些调用可能在不同的线程上,因此您可以在您的Servlet调用之间,不会在线程本地存储任何内容。但是对于您的服务方法的一次调用,它仍然可以。
HTH。