รูปแบบซิงเกิลตันเป็นหนึ่งใน 23 รูปแบบการออกแบบ มันเป็นรูปแบบการออกแบบที่ค่อนข้างง่ายโดยมีจุดประสงค์เพื่อส่งคืนวัตถุเดียวกันไม่ว่าจะถูกเรียกกี่ครั้งก็ตาม
แบ่งออกเป็น 2 โครงสร้าง แบบแรกคือแบบคนขี้เกียจ และอีกแบบคือแบบคนหิวโหย ต่างมีข้อดีและข้อเสียเป็นของตัวเอง
คลาสสาธารณะ เดี่ยว { ส่วนตัว คงที่ เดี่ยว = ใหม่ เดี่ยว() { } สาธารณะ เดี่ยว getInstance() { กลับเดี่ยว;
จากโปรแกรมข้างต้นจะเห็นได้ว่าแม้ว่าวัตถุประสงค์ของเราในการโหลดอ็อบเจ็กต์เดียวกันจะบรรลุผลสำเร็จแล้ว แต่อ็อบเจ็กต์เดียวจะถูกสร้างขึ้นเมื่อโหลดโปรแกรม เมื่อคลาสนี้มีวิธีการดังกล่าวหลายวิธี เราอาจไม่ได้ใช้มันส่วนใหญ่ ในวัตถุนี้จะทำให้เสียหน่วยความจำ ดังนั้นรูปแบบ singleton ขี้เกียจจึงเกิดขึ้น รหัสมีดังนี้:
คลาสสาธารณะ เดี่ยว { ส่วนตัว คงที่ เดี่ยว = null;
ด้วยวิธีนี้วัตถุจะใหม่ก็ต่อเมื่อเราเรียกมันจริง ๆ เท่านั้น แต่มีปัญหาในเรื่องนี้
เมื่อโค้ดชิ้นที่สองด้านบนถูกเรียกโดยสองเธรดเมื่อโหลดเป็นครั้งแรก จะมีการสร้างออบเจ็กต์ที่แตกต่างกันสองรายการ ดังนั้นจึงถือว่าเธรดไม่ปลอดภัย ในเวลานี้ คุณจะนึกถึงการเพิ่มล็อค ซึ่งเป็นโค้ดหลังจากการล็อค เป็นดังนี้:
คลาสสาธารณะเดี่ยว { ส่วนตัวคงที่เดี่ยว = null;
สิ่งนี้ทำให้บรรลุความปลอดภัยของเธรด แต่เมื่อวิธีการล็อคจำเป็นต้องดำเนินการหลายอย่าง การเรียกวิธีนี้จะใช้เวลานาน ซึ่งส่งผลร้ายแรงต่อเซิร์ฟเวอร์ เพราะหากเธรดยังคงเรียกใช้วิธีนี้ ไม่มีทางที่จะปรับเปลี่ยนได้ เธรดอื่น ๆ และเซิร์ฟเวอร์จะถูกบล็อก จากนั้นโค้ดที่อัปเกรดจะเป็นดังนี้:
คลาสสาธารณะ Single { priate static Single = null; } }
หลังจากการสังเกตอย่างรอบคอบ ฉันพบว่าไม่มีการล็อคในลักษณะนี้ เมื่อสองเธรดมาถึงเมธอด getInstance() หากพิจารณาเป็นครั้งแรก หนึ่งในนั้นจะต้องถูกบล็อก หลังจากที่อีกเธรดหนึ่งดำเนินการเสร็จสิ้น เธรดที่ถูกบล็อกจะถูกบล็อก ไม่อีกต่อไป เพื่อตรวจสอบว่าว่างเปล่าหรือไม่ วัตถุจะยังคงถูกสร้างขึ้น ด้วยวิธีนี้ จะมีการสร้างวัตถุหลายรายการ จากนั้นจึงอัปเกรดโค้ดที่ได้จะเป็นดังนี้:
คลาสสาธารณะเดี่ยว { ส่วนตัวคงที่ เดี่ยว = null; ส่วนตัวเดี่ยว () { } สาธารณะ GetInstance เดี่ยว () { ถ้า (single == null) { ซิงโครไนซ์ (Single.class) { ถ้า (single == null) { single = new Single (); } } } กลับเดี่ยว;
ด้วยวิธีนี้ ปัญหาข้างต้นจะไม่เกิดขึ้น และจะถูกล็อคเพียงครั้งเดียว เพราะเมื่อดำเนินการวิธีการนี้เป็นครั้งที่สอง การตัดสิน if จะถูกข้ามไป และ single จะถูกส่งกลับโดยตรง มันจะไม่ถูกล็อคอีกครั้ง และประสิทธิภาพการดำเนินการจะสูงมาก
แต่ถึงกระนั้นก็ยังมีปัญหาอยู่ เนื่องจากเราไม่สามารถแน่ใจได้ว่าวัตถุนั้นถูกกำหนดค่าไว้ในหน่วยความจำก่อนหรือวัตถุนั้นถูกสร้างขึ้นก่อน ดังนั้นโปรแกรมที่สองอาจได้รับวัตถุที่เตรียมใช้งานครึ่งหนึ่งใน jdk1 เราสามารถใช้คำสำคัญระเหยเพื่อหลีกเลี่ยงสถานการณ์นี้รหัสมีดังนี้:
คลาสสาธารณะเดี่ยว { ส่วนตัวระเหยคงที่ เดี่ยว = null; ส่วนตัวเดี่ยว () { } สาธารณะ GetInstance เดี่ยว () { ถ้า (single == null) { ซิงโครไนซ์ (Single.class) { ถ้า (single == null) { single = ใหม่ โสด(); } } } กลับเดี่ยว;
แต่สถานการณ์แบบนี้ไม่ค่อยได้ใช้ครับ ผมแค่มาเรียนรู้ อิอิ