[英]Spring Request scope vs java 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();
要么
SpringContext.getBean(SomeClass.class);
我想知道是否有人已经尝试过这样的基准测试?
如果我们考虑传统的Java方法,答案可以从下面的引用中减去,因为它要慢得多:
由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化。 因此,反射操作的性能低于非反射操作,并且应避免在性能敏感应用程序中频繁调用的代码段中。
引自JavaDoc的反思 - http://java.sun.com/docs/books/tutorial/reflect/index.html
所以,因为Spring使用了反射和getBean()
方法的SpringContext.getBean(SomeClass.class);
方法应该更慢。
编辑 :
另请注意, ThreadLocal
还嵌入了缓存 ,只要您在这些线程中重复使用信息肯定会更快。
关于ThreadLocal
解决方案,我想补充一点,您的Web服务器中可能存在一个线程池(例如:Tomcat),并且在完成每个请求后,您的线程局部变量实际上不会被清除,因为处理线程不会死已启用线程池。
您需要在threadLocal.remove()
每个请求时手动清除线程局部变量( threadLocal.remove()
)。 为此,您可以使用某些Spring请求/响应拦截器的某种afterCompletion()
。
Spring解决方案的成本会更高,但会使IMO更清晰。 获取,创建,初始化和存储bean涉及许多步骤。 但是,您不必像ThreadLocal
那样考虑清除请求范围的bean。 清除相应的ServletRequest
时将收集它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.