web-dev-qa-db-fra.com

Étendue de la demande Spring vs Java thread-local

En volume élevé (~ 50 000 requêtes par seconde) Java j'utilise ThreadLocal pour exécuter une tâche qui doit être exécutée par portée de requête).

Je pourrais obtenir le même effet en utilisant la portée de la demande Spring et je me demandais quel est le meilleur en termes de performances?

Dans le code, en utilisant ThreadLocal:

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

Et pour chaque paramètre de demande http:

myThreadLocal.set(new SomeClass());

Utilisation de l'étendue de demande Spring:

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

Maintenant, ce qui coûtera plus cher:

myThreadLocal.get();

OR

SpringContext.getBean(SomeClass.class);

Je me demande si quelqu'un a déjà essayé une telle référence?

18
forhas

Si nous considérons l'approche traditionnelle Java, la réponse peut être déduite du devis ci-dessous comme étant beaucoup plus lente:

Étant donné que la réflexion implique des types résolus dynamiquement, certaines optimisations de machine virtuelle Java Java ne peuvent pas être effectuées. Par conséquent, les opérations réfléchissantes ont des performances plus lentes que leurs homologues non réfléchissantes et doivent être évitées dans les sections de code qui sont fréquemment appelés dans les applications sensibles aux performances.

Extrait de JavaDoc sur la réflexion - http://Java.Sun.com/docs/books/tutorial/reflect/index.html

Donc, puisque Spring utilise Reflection avec la fonction getBean() La méthode SpringContext.getBean(SomeClass.class); devrait être plus lente.

[~ # ~] modifier [~ # ~] :

Notez également que le ThreadLocal a également la mise en cache intégrée afin que tant que vous réutilisez les informations dans ces threads, c'est certainement plus rapide.

12

Concernant la solution ThreadLocal je voudrais ajouter qu'il y a probablement un pool de threads sur votre serveur web (par exemple: Tomcat) et votre variable locale de thread ne sera pas réellement effacée à la fin de chaque requête en tant que threads de traitement ne mourez pas avec un pool de threads activé.

Vous devez effacer manuellement la variable thread-local (threadLocal.remove()) lors de la complétion de chaque requête. Pour cela, vous pouvez utiliser, par exemple, une sorte de afterCompletion() de certains de ces intercepteurs de demande/réponse Spring.

9
Artem Novikov

La solution Spring coûtera plus cher mais rendra le code IMO plus propre. La récupération, la création, l'initialisation et le stockage d'un bean nécessitent de nombreuses étapes. Cependant, vous n'aurez pas à penser à effacer le bean à portée de requête comme vous le feriez pour le ThreadLocal. Il sera collecté lorsque le ServletRequest correspondant sera nettoyé.

6