有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Spring请求范围与java线程本地

在高容量(每秒约50000个请求)的java web应用程序中,我使用ThreadLocal来执行一项任务,该任务应该在每个请求范围内执行

我可以使用Spring请求范围实现同样的效果,我想知道哪种性能更好

在代码中,使用ThreadLocal:

private static final ThreadLocal<SomeClass> myThreadLocal = new ThreadLocal<SomeClass>();

对于每个http请求设置:

myThreadLocal.set(new SomeClass());

使用Spring请求范围:

@Component
@Scope("request")
public class SomeClass{
...
}

现在,什么成本更高:

myThreadLocal.get();

SpringContext.getBean(SomeClass.class);

我想知道是否有人已经尝试过这样的基准


共 (3) 个答案

  1. # 1 楼答案

    如果我们考虑传统的java方法,答案可以从引用的BLLO中减去,因为速度要慢得多:

    Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

    引用JavaDoc中关于反射的内容-http://java.sun.com/docs/books/tutorial/reflect/index.html

    因此,由于SpringgetBean()方法中使用了反射,因此SpringContext.getBean(SomeClass.class);方法应该较慢

    编辑

    还请注意ThreadLocal还嵌入了缓存,因此只要在这些线程中重用信息,肯定会更快

  2. # 2 楼答案

    关于ThreadLocal解决方案,我想补充一点,您的web服务器中可能有一个线程池(例如:Tomcat),并且您的线程局部变量实际上不会在每个请求完成时被清除,因为在启用线程池的情况下,处理线程不会死亡

    您需要在每个请求完成后手动清除线程局部变量(threadLocal.remove())。例如,您可以使用一些Spring请求/响应拦截器的某种afterCompletion()

  3. # 3 楼答案

    Spring解决方案将花费更多,但将使IMO的代码更干净。获取、创建、初始化和存储bean涉及很多步骤。但是,您不必像清除ThreadLocal那样考虑清除请求范围的bean。当相应的ServletRequest被清除时,它将被收集