这只是在我的负载测试期间测试 Tomcat NIO 连接器时想到的。我还使用了 ThreadLocal,我还使用了 Spring,我知道它在几个地方也使用了它。
由于 NIO 连接器没有每个连接一个线程,我担心如果 ThreadLocal 对象在被清理之前与另一个线程共享,可能会导致很难找到错误。但是,我认为这不是问题,因为它不是我能找到的书面警告,我也没有找到任何其他关于此的警告帖子。我假设 NIO 连接器对服务于实际请求的线程没有影响。
在我做出这个假设之前,我希望找到一些具体的证据。
最佳答案
只有熟悉 Tomcat 代码的人才能给你一个具体的答案,但我会尝试一个木制的 :)
首先,您需要弄清楚您是指简单地使用 NIO 连接器还是指的是 Async servlet。 每种情况的答案都会略有不同。
要注意的主要事情是 Java 没有任何类型的延续、协同例程或线程重新调度。这意味着一旦您启动一段在线程上运行的代码,只有该段代码会在线程上运行,直到它完成。
因此,如果您有:myObject.doSomething();
那么在 doSomething
运行时,它具有对该线程的独占访问权。线程不会切换到其他代码段 - 无论您使用哪种 IO 模型。
可能(将会)发生的情况是,不同的线程将被安排在不同的 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 将在整个执行过程中设置为正确的值。
所以一个简单的 NIO 连接器应该没有什么区别——容器将调用 servlet 上的 service
方法,servlet 将在单个线程中执行,然后在最后完成。只是容器在处理连接时能够以更有效的方式处理 IO。
如果您使用的是异步 servlet,那么情况会有所不同 - 在这种情况下,您的 servlet 可能会针对单个请求被多次调用(由于异步模型的工作方式),并且这些调用可能在不同的线程上,所以你不能在你的 servlet 调用之间在线程本地存储一些东西。但是对于您的服务方法的单次调用,它仍然没问题。
HTH.
关于java - ThreadLocal 与 Tomcat NIO Connector 一起使用是否安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7925014/