J'ai une question concernant la manière dont singleton beans traite les demandes simultanées en détail.
J'ai cherché sur StackOverflow en ce qui concerne cette question. Ceci est un exemple lien de stackoverflow , mais je n'ai trouvé que des détails de haut niveau. Je veux des détails complets sur la manière dont un bean singleton traite les requêtes simultanées et comment le processeur système verra ces requêtes.
J'ai effectué des recherches sur le traitement des demandes simultanées dans le processeur système en ligne. Ils ont dit que le processeur lui-même a un ordonnanceur et que ce dernier décidera quelle requête sera traitée.
OK bien. Si je suppose que j'ai plusieurs processeurs principaux, comment le planificateur gère-t-il les demandes simultanées?
Est-ce que n'importe qui peut m'expliquer le processus étape par étape sur la façon dont un bean singleton servira des demandes concurrentes dans la JVM et le système?
Laissez-moi vous expliquer avec un exemple concret. J'ai une classe comme Sports
:
class Sports {
public void playFootball() {
}
public void playVolleyBall() {
}
}
Deux demandes arrivent. La première demande exécute la méthode playFootball
sur l'instance singleton créée de la classe Sports
. En même temps, une autre demande exécute la méthode playVolleyBall
sur la même instance singleton créée de la classe Sports
.
Comment est-ce possible avec une instance singleton?
Saravan Kumar,
Je comprends la motivation derrière votre question. Avant de commencer à travailler sur des compilateurs, j'avais également le même désir de connaître les éléments internes de la machine virtuelle Java.
Tout d'abord, votre question m'impressionne. Afin de résoudre votre question, il vous faut quelques points de distinction et de compréhension. Premièrement: Un modèle Singleton, ou parfois même un anti-modèle, garantit qu’une seule instance de cette classe est disponible pour la machine virtuelle Java (JVM). Cela signifie que nous introduisons essentiellement un état global dans une application. Je sais que vous comprenez cela, mais ce n’est qu’un éclaircissement.
Maintenant les internes.
Lorsque nous créons une instance d'une classe, nous créons un objet résidant dans la mémoire partagée de la machine virtuelle Java. Maintenant, ces threads exécutent indépendamment du code qui opère sur ces instances. Chaque thread a une mémoire de travail dans laquelle il conserve les données de la mémoire principale partagées par tous les threads. C'est ici que réside la référence à l'objet Singleton que vous avez créé. Ce qui se passe essentiellement, c’est que le bytecode généré et représentatif de l’objet singleton que vous avez créé est en cours d’exécution sur chacun de ces threads.
Voici comment cela se passe:
Chaque thread JVM a une pile JVM privée, créée en même temps que le thread. Maintenant, la machine virtuelle Java a un segment de mémoire partagé par tous les threads de la machine virtuelle Java. Le segment de mémoire est la zone de données d'exécution à partir de laquelle la mémoire est allouée pour toutes les instances de classe et les tableaux. Le segment de mémoire est créé au démarrage de VM. Lorsque votre thread demande l'instance singleton, il va pointer sur une référence dans le tas où réside le bytecode de ce singleton. Il va exécuter le code approprié. Dans votre cas, il va exécuter la première méthode pour la première requête et la deuxième méthode pour la seconde requête. Cela est possible parce qu'il n'y a pas de verrous ou de restrictions empêchant le compilateur de pointer le compteur de programme vers la zone du tas où cette instance est allouée. La seule restriction imposée par la classe Singleton à la machine virtuelle Java est qu’elle ne peut avoir qu’une seule instance dans le tas de cette classe. C'est tout simplement ça. En dehors de cela, vous pouvez y faire référence 100 fois plus longtemps, le compilateur va pointer vers le même bytecode et simplement l'exécuter. C'est pourquoi nous voulons généralement que la classe Singleton soit sans état, car si un thread y accède, nous ne voulons pas que les variables internes soient mutées à cause du manque de contrôle de concurrence.
S'il vous plaît laissez-moi savoir si vous avez des questions!
Un haricot singleton idéal ne devrait garder aucun état. Cela signifie qu'il n'y aura aucune variable qui stocke quoi que ce soit spécifique à la demande qu'il sert.
Ainsi, un bean singleton aura simplement un code sans état (par exemple, des méthodes de contrôleur) pouvant être exécuté simultanément pour plusieurs demandes sans aucun problème de simultanéité.
Par exemple si suit était votre bean singleton:
@Service
public class Calculator {
public int sum(int a, int b) {
return a + b;
}
}
En termes simples, lorsque deux "demandes" invoquent la méthode sum
du bean en même temps, cela signifie que la méthode sum
sera exécutée simultanément dans deux threads différents. Ils auront donc leur propre contexte d’exécution qui ne se chevauchera pas. Cela leur permettrait en toute sécurité de fonctionner simultanément.
Si le même haricot devait avoir l'état suivant:
@Service
public class Calculator {
int incrementalMultiplier = 0;
public int mulitply(int a, int b) {
incrementalMultiplier++;
return a * b * incrementalMultiplier;
}
}
Cela pourrait entraîner des problèmes lors du traitement simultané de deux demandes, car incrementalMultiplier
est l'état de niveau d'objet qui sera partagé par les deux demandes (threads) et pourrait donc produire des résultats inattendus.
En bref, un singleton sans état sera en mesure de répondre à deux requêtes simultanément car elles seront dans des threads différents.
J'ai vu beaucoup de réprimandes pour garder les beans singleton partagés sans état et je voulais présenter un cas d'utilisation où un singleton avec état dans une bean de support d'application Web a un sens.
J'ai une application Web d'administration qui, à la demande, interroge deux systèmes distincts (un CRM et un gestionnaire d'actifs numériques - DAM) pour les données utilisateur, compare les enregistrements et met à jour le DAM en conséquence en utilisant son API. Cela prend parfois beaucoup de temps s’il ya beaucoup de mises à jour. L'interface utilisateur Web affiche l'état des mises à jour en temps réel, au fur et à mesure que le navigateur interroge le bean de support à l'aide d'ajax toutes les secondes pour afficher une barre de progression et le nombre de comptes d'utilisateurs qu'il a traités. L'interface utilisateur fournit également un bouton pour démarrer le processus de synchronisation et un bouton pour l'arrêter. Le bouton de synchronisation est initialement activé et le bouton d'arrêt n'est pas rendu. Une fois que l'utilisateur a cliqué sur le bouton de démarrage, celui-ci est désactivé et le bouton d'arrêt est activé.
Lorsque la synchronisation est active, je souhaite que différents clients (différents utilisateurs du clavier utilisant l’application Web dans leurs navigateurs distincts) voient le même état, c’est-à-dire la barre de progression, le nombre de comptes d’utilisateur traités et les états des boutons. Ceci est important car il n’a aucun sens de lancer un deuxième processus de synchronisation alors qu’il est déjà en cours.
Pour plus de détails, comment le singleton Bean sert-il la demande simultanée? Vous devez connaître les éléments suivants concernant Spring Beans
Champs de haricots
Spring a différentes portées de bean (par exemple, Prototype, Singleton, etc.), mais toutes ces étendues sont appliquées dès la création du bean. Par exemple, un haricot "prototype" sera créé chaque fois que ce haricot est "injecté". .__ alors qu'un bean "singleton" sera créé une seule fois et partagé dans le contexte de l'application.
"singleton" scoped est la portée par défaut de Spring Bean.
Création de haricot
Le cycle de vie complet de Spring Bean est géré par le conteneur Spring (c'est-à-dire ApplicationContext/BeanFacotry) Spring Container fait référence en interne à la définition du bean (base ieXML ou Annotation) pour la création d'instances réelles. définition de bean . maintenant, lorsque Spring Container est lancé, il fait référence à la définition de bean et instate tout le bean défini.
Demander le haricot.
Désormais, lorsque votre objet adressera une requête au bean, Spring Container transmettra le bean déjà initialisé.
j'espère que ceci vous aidera...