Spring请求范围vs java thread-local

时间:2014-08-20 13:33:39

标签: java spring thread-local

高容量(每秒大约50,000个请求)java web-app我正在使用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();

OR

SpringContext.getBean(SomeClass.class);

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

3 个答案:

答案 0 :(得分:9)

如果我们考虑传统的Java方法,答案可以从下面的引文中扣除,因为它要慢得多:

  

因为反射涉及动态解析的类型,   无法执行某些Java虚拟机优化。   因此,反射操作的性能比它们慢   非反射对应物,应避免代码部分   在性能敏感的应用程序中经常调用它们。

引自JavaDoc关于反思 - http://java.sun.com/docs/books/tutorial/reflect/index.html

因为 Spring 使用反射getBean()方法,SpringContext.getBean(SomeClass.class);方法应该更慢。

修改

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

答案 1 :(得分:6)

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

答案 2 :(得分:6)

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

您需要在收集每个请求时手动清除线程局部变量(threadLocal.remove())。为此,您可以使用某些afterCompletion()部分Spring请求/响应拦截器。