คำนำ
เมื่อเร็ว ๆ นี้ฉันพบปัญหาการหยุดชะงักเมื่อเริ่มโครงการฤดูใบไม้ผลิ เมื่อใช้ JStack เพื่อรับสแต็กเธรดคุณจะเห็นว่าสองเธรดมีการหยุดชะงัก:
กระบวนการแก้ปัญหา:
ซอร์สโค้ดของ DefaultSingletonBeanRegistry.getSingleton() มีดังนี้ คุณจะเห็นได้ว่าวิธีนี้ต้องการให้ SingletonObjects ถูกล็อค
ซอร์สโค้ดของ xxx.subject.core.cache.datalocalcacheinit.afterpropertiesset มีดังนี้:
คุณจะเห็นว่าเมื่อถั่วนี้เริ่มต้นมันจะเริ่มต้นเธรดและเรียกใช้วิธี initData() ของถั่วอีกตัวเพื่อโหลดข้อมูลจากฐานข้อมูล การเริ่มต้นของ datalocalcacheinit bean จะได้รับการพิจารณาให้เสร็จสมบูรณ์หลังจากโหลดข้อมูล
จากสแต็คข้างต้นเราจะเห็นได้ว่าเมื่อภาชนะสปริงเริ่มต้นถั่วมันจะล็อควัตถุ SingletonObjects; เราเปิดเธรดในเมธอด afterPropertiesSet() ซึ่งในที่สุดจะทำให้เกิดสปริงเพื่อโหลดถั่วอีกตัว เธรดแรก (เธรดหลักที่เริ่มต้นสปริง) ไม่ได้ปล่อยล็อคและเธรดที่สอง (เธรดที่เปิดด้วยตัวเอง) ก็ต้องได้รับการล็อควัตถุ SingletonObjects ซึ่งทำให้เกิดการหยุดชะงัก ปรากฏการณ์ที่แสดงคือภาชนะสปริงติดอยู่ที่นั่นและไม่สามารถเริ่มต้นการเริ่มต้นของถั่วทั้งหมดได้
ลองมาดูตัวอย่างซึ่งคล้ายกับรหัสจริงในโครงการของเรา FirstBean เรียกวิธีการใน Confighelper:
ชั้นเรียนสาธารณะ FirstBean ใช้การเริ่มต้นเบียน {@Override โมฆะสาธารณะ AfterPropertIesset () โยนข้อยกเว้น {System.out.println ("ถั่วแรกเริ่มต้น .... "); blockingqueue queue = new ArrayblockingQueue (10); เธรดเธรด = ใหม่เธรด () {@Override โมฆะสาธารณะเรียกใช้ () {confighelper.dosomething (); queue.add (1); - thread.start (); queue.take (); System.out.println ("รับข้อมูลก่อน .... "); - รหัส confighelper มีดังนี้: รับถั่วอีกตัวผ่าน beanfactory
คลาสสาธารณะ Confighelper ใช้ beanfactoryaware {โรงงานผลิตถั่วคงที่ส่วนตัว; @Override โมฆะสาธารณะ setBeanFactory (BeanFactory beanfactory) พ่น beansexception {this.factory = beanfactory; } โมฆะคงที่สาธารณะ dosomething () {secondBean Bean = (secondBean) Factory.getBean ("Second"); Bean.say (); - รหัส SecondBean นั้นง่ายดังนี้:
ชั้นเรียนสาธารณะ SecondBean {โมฆะสาธารณะพูด () {System.out.println ("SecondBean ... "); -ไฟล์การกำหนดค่าสปริงและรหัสเริ่มต้นมีดังนี้ คุณสามารถค้นหาการหยุดชะงักเมื่อทำงาน:
<? xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id = "config" id = "second"> </ebean> </ebeans> คลาสสาธารณะชั้นหลัก {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {applicationcontext context = new filesystemxmlapplicationContext ("src/main/java/net/aty/spring/deadlock/deadlock.xml");เมื่อฤดูใบไม้ผลิเริ่มต้นถ้าเราเริ่มเธรดเพื่อรับถั่วที่จุดขยายบางจุดที่จัดทำโดยฤดูใบไม้ผลิ (Beanfactoryaware/InitializingBean ฯลฯ ) คอนเทนเนอร์จะถูกปิดกั้น เพราะฤดูใบไม้ผลิเริ่มต้นถั่วซิงเกิล (ถั่วส่วนใหญ่เป็นซิงเกิล) จะเพิ่มล็อค หากการล็อคยังไม่ได้รับการปล่อยตัวเมื่อเริ่มต้นถั่ว 1 ครั้งและเธรดอื่นจะกระตุ้นถั่วสปริงโหลดอีกครั้งการหยุดชะงักจะปรากฏขึ้น
การแก้ปัญหาข้างต้นนั้นง่ายมาก: FirstBean มีเหตุผลขึ้นอยู่กับ Confighelper และ SecondBean แต่เราไม่ได้แสดงความสัมพันธ์เชิงตรรกะของฤดูใบไม้ผลิ เมื่อสปริงเริ่มต้น FirstBean ให้ป้อน afterPropertiesSet() วิธีนี้จะกระตุ้นการโหลดของถั่วอีก 2 ตัวเมื่อเปิดเธรด เราเพียงแค่ต้องแสดงการพึ่งพาของฤดูใบไม้ผลิและปล่อยให้สปริงโหลด Configenlper และ SecondBean ก่อน
<bean id = "config" ขึ้นอยู่กับ = "second"> </epean> <bean id = "First" ขึ้นอยู่กับ = "config"> </epean> <bean id = "Second"> </ebean>
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com