การใช้โหมด Singleton (5 ประเภท)
ใช้กันทั่วไป:
สไตล์หิว (เธรดปลอดภัยประสิทธิภาพการโทรสูง แต่ไม่สามารถโหลดได้ในลักษณะล่าช้า)
สไตล์ขี้เกียจ (เธรดปลอดภัยประสิทธิภาพการโทรต่ำสามารถโหลดได้อย่างล่าช้า)
อื่น:
ประเภทล็อคการตรวจจับสองครั้ง (เนื่องจากโมเดลภายในของ JVM จะมีปัญหาเป็นครั้งคราวและจะไม่ถูกสร้างและใช้)
ชั้นเรียนภายในแบบคงที่ (เธรดปลอดภัยประสิทธิภาพการโทรสูง แต่สามารถโหลดได้ในลักษณะล่าช้า)
ระบุ Singletons (Thread-Safe ประสิทธิภาพการโทรสูงและไม่สามารถโหลดได้ในความล่าช้า)
รหัสเฉพาะของ Singleton of Hungry Man มีดังนี้:
แพ็คเกจ com.lcx.mode; /** * * ซิงเกิลของคนที่หิวโหย ไม่ว่าจะใช้วัตถุนี้ในอนาคตหรือไม่ก็ตามเราสร้างอินสแตนซ์ของวัตถุนี้ตั้งแต่ต้น * เมื่อจำเป็นเราจะส่งคืนวัตถุอินสแตนซ์ที่สร้างขึ้นดังนั้นเราจึงค่อนข้างหิวดังนั้นนี่จึงเรียกว่าซิงเกิลของคนที่หิวโหย * @author qq1013985957 * */ คลาสสาธารณะ Singletonhanger {ส่วนตัวคงที่ Singletonhanger อินสแตนซ์ = ใหม่ Singletonhanger (); Private SingletonHanger () {} สาธารณะคงที่ Singletonhanger GetInstance () {อินสแตนซ์กลับ; }} /*** Singleton สไตล์ฮันขี้เกียจเมื่อต้องการวัตถุซิงเกิลตันมันจะสร้างวัตถุซิงเกิลเพียงชิ้นเดียวและเรียกมันอีกครั้งในภายหลังและวัตถุซิงเกิลที่ส่งคืนนั้นเป็นวัตถุซิงเกิลที่สร้างขึ้นครั้งแรก* เริ่มต้นสมาชิกคงที่ * @author QQ1013985957 * */ คลาส SingletonLazy {อินสแตนซ์ SingletonLazy ส่วนตัว = NULL; Private SingletonLazy () {} /*** Singleton ที่ใช้โดยวิธีนี้ไม่สามารถใช้ในหลายเธรดได้ หลายบรรทัดสามารถป้อนวิธี IF ในเวลาเดียวกันซึ่งจะทำให้วัตถุซิงเกิลหลายชิ้นถูกสร้างขึ้น * @return */ สาธารณะ singletonlazy getInstance1 () {ถ้า (อินสแตนซ์ == null) {อินสแตนซ์ = ใหม่ singletonlazy (); } return อินสแตนซ์; } /*** ทุกคนจะนึกถึงการซิงโครไนซ์ วิธีการแบบซิงโครนัสสามารถใช้ Singleton แบบมัลติเธรด* อย่างไรก็ตามวิธีนี้ไม่เป็นที่ต้องการและส่งผลกระทบต่อประสิทธิภาพอย่างจริงจัง เนื่องจากวิธีการจะต้องตรวจสอบทุกครั้งที่คุณได้รับซิงเกิลตันคุณสามารถใช้บล็อกรหัสที่ซิงโครไนซ์เพื่อให้ได้การซิงโครไนซ์ * @return */ สาธารณะแบบคงที่ซิงโครไนซ์ singletonlazy getInstance2 () {ถ้า (อินสแตนซ์ == null) {อินสแตนซ์ = ใหม่ singletonlazy (); } return อินสแตนซ์; } /*** ใช้บล็อกรหัสที่ซิงโครไนซ์เพื่อใช้บล็อกรหัสที่ซิงโครไนซ์ในวิธีการ IF เพื่อตรวจสอบว่ามีซิงเกิลตันอยู่หรือไม่และตรวจสอบอีกครั้งในบล็อกรหัสที่ซิงโครไนซ์ไม่ว่าจะมีการสร้างซิงเกิล * นี่คือวิธีการตรวจสอบการล็อคบนอินเทอร์เน็ตสองครั้ง * @return */ สาธารณะแบบคงที่ singletonlazy getInstance3 () {ถ้า (อินสแตนซ์ == null) {ซิงโครไนซ์ (singletonlazy.class) {ถ้า (อินสแตนซ์ == null) {อินสแตนซ์ = ใหม่ }}} ส่งคืนอินสแตนซ์; }} /*** ใช้การแจงนับเพื่อใช้โหมดซิงเกิลตันซึ่งเป็นวิธีที่แนะนำในการใช้ในการสร้างอินสแตนซ์ Java* ที่มีประสิทธิภาพตามสถานการณ์เฉพาะ สำหรับนักเรียนที่ไม่คุ้นเคยกับ enums คุณสามารถอ้างถึงความเข้าใจเบื้องต้นของชั้นเรียนการแจงนับบล็อก Java ของฉัน * ประโยชน์ของมัน: มันกระชับมากขึ้นและให้กลไกการทำให้เป็นอนุกรมฟรีป้องกันการสร้างอินสแตนซ์หลายครั้งอย่างแน่นอนแม้ในการเผชิญกับลำดับที่ซับซ้อนและการโจมตีแบบสะท้อนกลับ * @author qq1013985957 * */ enum singletionenum {singletionenum ("singleton enum"); สตริงส่วนตัว Str; Private Singletionenum (String str) {this.setstr (str); } สตริงสาธารณะ getStr () {return str; } โมฆะสาธารณะ setstr (string str) {this.str = str; - รูปแบบ Singleton ข้างต้นไม่ได้ทดสอบ คุณสามารถทดสอบเพื่อตรวจสอบว่า hashcode ของวัตถุมีความสอดคล้องกันเพื่อตรวจสอบว่าเป็นวัตถุเดียวกันหรือไม่
วิธีการที่ชั่วร้ายและขี้เกียจไม่สามารถป้องกันการสะท้อนจากการใช้หลายกรณี ผ่านการสะท้อนการตั้งค่าวิธีการเข้าถึงได้วิธีการที่สามารถเข้าถึงได้สามารถเรียกตัวสร้างส่วนตัวได้ คุณสามารถปรับเปลี่ยนคอนสตรัคเตอร์เพื่อโยนข้อยกเว้นเมื่อถูกขอให้สร้างอินสแตนซ์ที่สอง
ในความเป็นจริงสิ่งนี้ไม่สามารถรับประกันได้ว่าซิงเกิล หลังจากการทำให้เป็นอนุกรม Deserialization สามารถสร้างอินสแตนซ์ใหม่และเพิ่มวิธีการ readresolve () ลงในคลาส Singleton เพื่อป้องกันได้
รหัส Singleton สไตล์คนขี้เกียจมีดังนี้:
แพ็คเกจ com.lcx.mode; นำเข้า Java.io.File; นำเข้า Java.io.FileInputStream; นำเข้า Java.io.FileOutputStream; นำเข้า Java.io.ObjectInputStream; นำเข้า Java.io.ObjectOutputStream; นำเข้า java.io.serializable; นำเข้า java.lang.reflect.constructor; นำเข้า java.lang.reflect.invocationTargetException; /*** Singletons สไตล์คนขี้เกียจถูกสร้างขึ้นเมื่อต้องการวัตถุซิงเกิลตัน เมื่อต้องการวัตถุซิงเกิลตันมันจะถูกเรียกอีกครั้งในภายหลัง วัตถุซิงเกิลที่ส่งคืนนั้นยังเป็นวัตถุซิงเกิลตันที่สร้างขึ้นครั้งแรก* เริ่มต้นสมาชิกคงที่เป็นโมฆะและสร้างมันขึ้นมาเมื่อได้รับซิงเกิลตันดังนั้นจึงเรียกว่าสไตล์คนขี้เกียจ * @author QQ1013985957 * */ คลาสสาธารณะ Singleton ใช้ serializable {/ ** * */ ส่วนตัวคงที่สุดท้ายสุดท้าย SerialVersionUid = -5271537207137321645L; อินสแตนซ์แบบสแตติกส่วนตัว = NULL; INT คงที่ส่วนตัว i = 1; Private Singleton () { / *** ป้องกันการโจมตีแบบสะท้อนกลับเรียกใช้และเรียกคอนสตรัคเตอร์เพียงครั้งเดียว } else {โยน runtimeException ใหม่ ("ตัวสร้างสามารถเรียกได้เพียงครั้งเดียว"); } System.out.println ("Call Private Constructor ของ Singleton"); } /*** ใช้บล็อกรหัสที่ซิงโครไนซ์เพื่อใช้บล็อกรหัสที่ซิงโครไนซ์ในวิธีการ IF เพื่อตรวจสอบว่ามีซิงเกิลตันอยู่หรือไม่และตรวจสอบอีกครั้งในบล็อกรหัสที่ซิงโครไนซ์ไม่ว่าจะมีการสร้างซิงเกิล * นี่คือสิ่งที่อินเทอร์เน็ตเรียกวิธีการล็อคการตรวจสอบซ้ำสองครั้ง * @return */ สาธารณะแบบสแตติกแบบสแตติกที่ซิงโครไนซ์ getInstance () {ถ้า (อินสแตนซ์ == null) {ซิงโครไนซ์ (singleton.class) {ถ้า (อินสแตนซ์ == null) {อินสแตนซ์ = ใหม่ singleton (); }} ส่งคืนอินสแตนซ์; } /*** ป้องกันไม่ให้ความเท่าเทียมกันสร้างวัตถุซิงเกิลใหม่ นี่คือสิ่งที่กล่าวไว้ในหนังสือ Java ที่มีประสิทธิภาพ วิธีนี้สามารถป้องกันได้ ฉันไม่เข้าใจรายละเอียดเฉพาะ * @return */ วัตถุส่วนตัว readresolve () {return instance; } โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น {test1 (); test2 (); } / *** การทดสอบ Desequence ยังคงเป็นโหมด Singleton* @throws Exception* / Public Static Void Test2 () พ่นข้อยกเว้น {Singleton S = singleton.getInstance (); ObjectOutputStream ObjectOutputStream = ใหม่ ObjectOutputStream (ใหม่ fileOutputStream (ไฟล์ใหม่ ("e: //singleton.txt")))); ObjectOutputStream.writeObject (s); ObjectInputStream ObjectInputStream = ใหม่ ObjectInputStream (ใหม่ FileInputStream (ไฟล์ใหม่ ("e: //singleton.txt"))))); Object ReadObject = ObjectInputStream.readObject (); Singleton S1 = (Singleton) ReadObject; System.out.println ("S.HashCode ():"+S.HASHCODE ()+", S1.HASHCODE ():"+S1.HASHCODE ()); ObjectOutputStream.flush (); ObjectOutputStream.close (); ObjectInputStream.close (); ObjectInputStream.close (); } / *** การทดสอบการโจมตีแบบทดสอบ* @throws Exception* / โมฆะคงที่สาธารณะ test1 () {singleton s = singleton.getInstance (); คลาส C = Singleton.class; Privateconstructor ของ Constructor; ลอง {privateConstructor = c.getDeclaredConstructor (); Privateconstructor.setAccessible (จริง); Privateconstructor.newinstance (); } catch (exception e) {e.printstacktrace (); -ตรวจสอบผลลัพธ์การโจมตีแบบสะท้อนกลับ:
หากไม่ได้เพิ่มผลลัพธ์ของวิธี readResolve:
ผลลัพธ์ของการเพิ่มวิธีการ readresolve:
ขอบคุณสำหรับการอ่านฉันหวังว่ามันจะช่วยคุณได้ ขอบคุณสำหรับการสนับสนุนเว็บไซต์นี้!