Préface
Récemment, j'ai rencontré un problème de blocage lors du démarrage du projet de printemps. Lorsque vous utilisez JSTACK pour obtenir la pile de threads, vous pouvez voir que deux threads ont des impasses:
Processus de solution:
Le code source de DefaultSingletonBeanRegistry.getSingleton() est le suivant. Vous pouvez voir que cette méthode nécessite que les singletonObjects soient verrouillés.
Le code source du deuxième xxx.subject.core.cache.datalocalcacheinit.afterpropertiesset est le suivant:
Vous pouvez voir que lorsque ce bean est initialisé, il démarrera le thread et appellera initData() d'un autre bean pour charger les données de la base de données. L'initialisation du bean de datalocalcacheinit sera considérée comme complète après le chargement des données.
À partir de la pile ci-dessus, nous pouvons voir que lorsque le conteneur à ressort initialise le bean, il verrouillera l'objet singletonObjects; Nous ouvrons un thread dans afterPropertiesSet() , qui finira par déclencher le ressort pour charger un autre bean. Le premier thread (le fil principal qui initialise le ressort) n'a pas libéré le verrou, et le deuxième fil (le fil qui est ouvert seul) doit également obtenir le verrou d'objet singletonObjects, qui provoque une impasse. Le phénomène indiqué est que le récipient à ressort est coincé là-bas et ne peut pas compléter l'initialisation de tous les haricots.
Jetons un coup d'œil à un exemple, qui est très similaire au code réel de notre projet. FirstBean appelle la méthode de Confightelper:
La classe publique FirstBean implémente InitializingBean {@Override public void AfterPropertiseSet () lève une exception {System.out.println ("First Bean initialize ...."); BlockingQueue Queue = nouveau ArrayBlockingQueue (10); Thread Thread = new Thread () {@Override public void run () {CONFIGHELPER.DOSOMETHing (); queue.add (1); }}; thread.start (); queue.take (); System.out.println ("First Get Data ...."); }} Le code CONFIGHELPER est le suivant: Obtenez un autre haricot via Beanfactory
Classe publique Confightelper implémente BeanfactoryAware {Factory privée statique de beanfactory; @Override public void SetBeanFactory (beanfactory beanfactory) lève BeanSexception {this.factory = beanfactory; } public static void doSomething () {SecondBean Bean = (SecondBean) factory.getBean ("second"); bean.say (); }} Le code SecondBean est simple comme suit:
classe publique SecondBean {public void Say () {System.out.println ("SecondBean ..."); }}Le fichier de configuration de Spring et le code de démarrage sont les suivants. Vous pouvez trouver des impasses en cours d'exécution:
<? xml version = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmlschema-instance" XSI: ScheMalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "config"> </Ean> <ean id = "First"> </ean> <ean id = "seconde" </bars> public class main {public static void main (string [] args) {applicationContext context = new FileSystemXmlApplicationContext ("src / main / java / net / aty / spring / deadlock / daadlock.xml"); // Chargement du fichier de configuration de Spring}}}Lorsque le printemps est initialisé, si nous commençons le fil pour acquérir le haricot à certains points d'extension fournis par Spring (BeanfactoryAware / InitializingBean, etc.), le conteneur sera bloqué. Parce que le printemps initialise les haricots singleton (la plupart des haricots sont des singletons) ajouteront des serrures. Si le verrou n'a pas été libéré lorsque 1 haricot est initialisé et qu'un autre thread déclenche à nouveau le haricot à ressort, une impasse apparaîtra.
La résolution du problème ci-dessus est simple: FirstBean dépend logiquement de Confightelper et SecondBean, mais nous ne montrons pas la relation logique du printemps. Lorsque Spring initialise FirstBean, entrez afterPropertiesSet() . Cette méthode déclenchera le chargement des 2 autres haricots lorsque le fil est allumé. Nous avons juste besoin de montrer la dépendance de Spring et de laisser le Spring charger le Confightelper et le SecondBean en premier.
<bean id = "config" Dentend-on = "Second"> </Ean> <Bean Id = "First" Depend-on = "Config"> </EAN> <Bean Id = "Second"> </Ean>
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.