web-dev-qa-db-ja.com

Spring Requestスコープvs Javaスレッドローカル

大量(1秒あたり〜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);

誰かがすでにそのようなベンチマークを試したことがあるのだろうか?

18
forhas

従来のJava=アプローチを考えると、答えは非常に遅いので以下の引用から差し引くことができます。

リフレクションには動的に解決されるタイプが含まれるため、特定のJava仮想マシンの最適化は実行できません。そのため、リフレクト操作は非リフレクト操作よりもパフォーマンスが遅いため、コードのセクションでは避ける必要がありますこれは、パフォーマンスに敏感なアプリケーションで頻繁に呼び出されます。

リフレクションに関するJavaDocからの引用- http://Java.Sun.com/docs/books/tutorial/reflect/index.html

したがって、SpringgetBean()Reflectionを使用するため、メソッドSpringContext.getBean(SomeClass.class);アプローチは遅くなるはずです。

[〜#〜]編集[〜#〜]

また、ThreadLocalにもcaching embeddedが含まれているため、これらのスレッドで情報を再利用する限り、確実に高速になります。

12

ThreadLocalソリューションに関して、おそらくWebサーバーにスレッドプールがあり(例:Tomcat)、スレッドローカル変数は、各要求が処理スレッドとして完了すると実際にはクリアされないことを追加したいと思います。スレッドプールを有効にした状態で死なないでください。

各リクエストの完了時に、スレッドローカル変数(threadLocal.remove())を手動でクリアする必要があります。たとえば、Springのリクエスト/レスポンスインターセプターのいくつかのafterCompletion()を使用できます。

9
Artem Novikov

Springソリューションはコストがかかるになりますが、コードがよりきれいなIMOになります。 Beanのフェッチ、作成、初期化、および格納には、多くの手順が含まれます。ただし、ThreadLocalのようにリクエストスコープBeanをクリアすることを考える必要はありません。対応するServletRequestがクリーンアップされるときに収集されます。