ThreadLocal是否可以安全地与Tomcat NIO Connector一起使用

Dav*_*vid 7 java tomcat nio thread-local

在负载测试期间测试Tomcat NIO连接器时,我们想到了这一点.我使用ThreadLocal另外我使用Spring,我知道在几个地方它也使用它.

由于NIO连接器每个连接没有一个线程,我担心如果ThreadLocal对象在清理之前与另一个线程共享,则可能导致很难找到错误.但是,我认为这不是一个问题,因为它不是我能找到的文件警告,也没有发现任何其他帖子警告这一点.我假设NIO连接器对服务于实际请求的线程没有影响.

在我采用这个假设之前,我希望找到一些具体的证据.

Tim*_*Tim 7

只有熟悉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);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后没有什么可担心的 - doSomethingElse将运行一个单个线程,并将threadlocal设置为整个执行的正确值.

因此,简单的NIO连接器应该没有区别 - 容器将调用serviceservlet上的方法,servlet将在单个线程中执行,然后最后完成所有操作.只是容器能够在处理连接时以更有效的方式处理IO.

如果您正在使用异步servlet,那么它会有所不同 - 在这种情况下,您的servlet可能会针对单个请求多次调用(因为异步模型的工作方式),并且这些调用可能位于不同的线程上,因此您可以在servlet的调用之间存储一些线程本地的东西.但是对于一次调用您的服务方法,它仍然没问题.

HTH.