ตัววนซ้ำใน Java มีสองประเภท: fail-safe และ fail-fast
นี่หมายความว่าอย่างไรและความแตกต่างระหว่างพวกเขาคืออะไร?
ตัววนซ้ำใน Java มีสองประเภท: fail-safe และ fail-fast
นี่หมายความว่าอย่างไรและความแตกต่างระหว่างพวกเขาคืออะไร?
คำตอบ:
อะไรคือความแตกต่างระหว่างพวกเขา ...
"Fail-safe" ( ในทางวิศวกรรม ) หมายถึงสิ่งที่ล้มเหลวในลักษณะที่ไม่ก่อให้เกิดความเสียหายน้อยที่สุด พูดอย่างเคร่งครัดไม่มีสิ่งดังกล่าวใน Java เป็นตัววนซ้ำที่ไม่ปลอดภัย หากตัววนซ้ำล้มเหลว (ในความหมายปกติของ "ล้มเหลว") คุณสามารถคาดหวังความเสียหายที่จะเกิดขึ้นได้
ฉันสงสัยว่าคุณหมายถึงตัวทำซ้ำที่ "สม่ำเสมอเพียงเล็กน้อย" Javadoc พูดว่า:
"การใช้งานคอลเลคชันพร้อมกันส่วนใหญ่ (รวมถึงคิวส่วนใหญ่) ยังแตกต่างจากอนุสัญญา java.util ตามปกติตรงที่ Iterators และ Spliterators ให้ความสอดคล้องกันเล็กน้อยมากกว่าการส่งผ่านที่ล้มเหลวอย่างรวดเร็ว"
โดยทั่วไปความสอดคล้องที่อ่อนแอหมายความว่าหากมีการแก้ไขคอลเลกชันพร้อมกับการวนซ้ำการรับประกันสิ่งที่เห็นซ้ำจะอ่อนแอลง (รายละเอียดจะระบุไว้ใน javadocs คลาสคอลเลกชันพร้อมกันแต่ละคลาส)
"Fail-fast" ( ในการออกแบบระบบ ) หมายความว่าเงื่อนไขความล้มเหลวจะได้รับการตรวจสอบอย่างเข้มงวดเพื่อให้ตรวจพบเงื่อนไขความล้มเหลว (หากเป็นไปได้1 ) ก่อนที่จะเกิดความเสียหายมากเกินไป ใน Java ตัววนซ้ำแบบเร็วที่ล้มเหลวจะล้มเหลวโดยการโยนไฟล์ConcurrentModificationException
.
อีกทางเลือกหนึ่งสำหรับ "ล้มเหลว - เร็ว" และ "ไม่สอดคล้องกัน" คือความหมายที่การวนซ้ำล้มเหลวโดยไม่สามารถคาดเดาได้ เช่นบางครั้งให้คำตอบผิดหรือโยนข้อยกเว้นที่ไม่คาดคิด (นี่คือลักษณะการทำงานของการใช้งานมาตรฐานบางอย่างของEnumeration
API ใน Java เวอร์ชันแรก ๆ )
... และแตกต่างจากตัววนซ้ำที่เราใช้ในการรวบรวมหรือไม่
ไม่ใช่คุณสมบัติเหล่านี้เป็นคุณสมบัติของตัวทำซ้ำที่ใช้โดยประเภทคอลเล็กชันมาตรฐาน คือพวกเขามีทั้ง "ล้มเหลวอย่างรวดเร็ว" หรือ "ที่สอดคล้องกันนิดหน่อย" ... เมื่อใช้อย่างถูกต้องเกี่ยวกับการประสานและหน่วยความจำแบบ Java 1
โดยทั่วไปแล้วตัวทำซ้ำแบบเร็วที่ล้มเหลวจะถูกนำไปใช้โดยใช้ตัวvolatile
นับบนวัตถุคอลเลกชัน
Iterator
สร้างค่าปัจจุบันของตัวนับจะฝังอยู่ในIterator
ออบเจ็กต์Iterator
การดำเนินการเมธอดจะเปรียบเทียบค่าตัวนับทั้งสองและพ่น CME หากค่าต่างกันในทางตรงกันข้ามตัวทำซ้ำที่มีความสม่ำเสมอน้อยมักจะมีน้ำหนักเบาและใช้ประโยชน์จากคุณสมบัติของโครงสร้างข้อมูลภายในของคอลเล็กชันแต่ละชุดพร้อมกัน ไม่มีรูปแบบทั่วไป หากคุณสนใจโปรดอ่านซอร์สโค้ดสำหรับคลาสคอลเลคชันต่างๆ
1 - ไรเดอร์คือพฤติกรรมที่ล้มเหลวอย่างรวดเร็วถือว่า ID แอปพลิเคชันถูกต้องตามการซิงโครไนซ์และโมเดลหน่วยความจำ นั่นหมายความว่า (ตัวอย่างเช่น) หากคุณทำซ้ำArrayList
โดยไม่มีการซิงโครไนซ์ที่เหมาะสมผลลัพธ์อาจเป็นผลลัพธ์ของรายการที่เสียหาย กลไก "ล้มเหลวอย่างรวดเร็ว" อาจตรวจพบการแก้ไขพร้อมกัน (แม้ว่าจะไม่ได้รับการรับรอง) แต่จะไม่ตรวจพบการทุจริตที่อยู่ภายใต้ ตัวอย่างเช่นjavadocสำหรับVector.iterator()
กล่าวว่า:
"พฤติกรรมที่ล้มเหลวอย่างรวดเร็วของตัววนซ้ำไม่สามารถรับประกันได้อย่างที่เป็นอยู่โดยทั่วไปแล้วเป็นไปไม่ได้ที่จะทำการรับประกันอย่างหนักหน่วงใด ๆ เมื่อมีการปรับเปลี่ยนพร้อมกันที่ไม่ซิงโครไนซ์ตัวทำซ้ำที่เร็วล้มเหลวจะ
ConcurrentModificationException
ใช้ความพยายามอย่างเต็มที่ดังนั้นจึงเป็น ผิดในการเขียนโปรแกรมที่ขึ้นอยู่กับข้อยกเว้นนี้เพื่อความถูกต้อง: ควรใช้ลักษณะการทำงานที่ล้มเหลวอย่างรวดเร็วของตัววนซ้ำเพื่อตรวจหาจุดบกพร่องเท่านั้น "
เป็นประเภทที่ค่อนข้างล้มเหลวเร็วและไม่สอดคล้องกัน:
ตัวทำซ้ำจากjava.util
แพ็กเกจโยนConcurrentModificationException
หากคอลเลกชันถูกแก้ไขโดยวิธีการของคอลเลกชัน (เพิ่ม / ลบ) ในขณะที่ทำซ้ำ
java.util.concurrent
โดยทั่วไปแล้วตัววนซ้ำจากแพ็กเกจจะวนซ้ำบนสแน็ปช็อตและอนุญาตให้มีการแก้ไขพร้อมกัน แต่อาจไม่สะท้อนถึงการอัปเดตคอลเล็กชันหลังจากสร้างตัววนซ้ำแล้ว
Iterator
หรือEnumeration
ระบุลักษณะการทำงานว่าล้มเหลวอย่างรวดเร็วหรือไม่ปลอดภัย เป็นการใช้งานเฉพาะ (เช่นวิธีการรวบรวมiterator()
/ elements()
etc เฉพาะที่ส่งคืนวัตถุเหล่านี้) ที่ระบุลักษณะการทำงาน 2) การใช้งานการแจงนับทั่วไปจะไม่ล้มเหลวได้อย่างรวดเร็วหรือไม่ปลอดภัย
ข้อแตกต่างเพียงอย่างเดียวคือตัวทำซ้ำที่ไม่ปลอดภัยไม่ได้โยนข้อยกเว้นใด ๆ ตรงกันข้ามกับ Iterator ที่ล้มเหลวอย่างรวดเร็ว
หากคอลเล็กชันถูกปรับเปลี่ยนโครงสร้างในขณะที่เธรดหนึ่งกำลังทำซ้ำ นี่เป็นเพราะพวกเขาทำงานบนโคลนของคอลเล็กชันแทนที่จะเป็นคอลเลกชันดั้งเดิมและนั่นคือเหตุผลที่พวกเขาถูกเรียกว่าเป็นตัววนซ้ำที่ไม่ปลอดภัย
Iterator ของ CopyOnWriteArrayList เป็นตัวอย่างของ Iterator ที่ไม่ปลอดภัยและตัววนซ้ำที่เขียนโดย ConcurrentHashMap keySet ยังเป็นตัววนซ้ำที่ไม่ปลอดภัยและอย่าโยน ConcurrentModificationException ใน Java
สถานการณ์นี้เกี่ยวข้องกับ "การประมวลผลพร้อมกัน" หมายความว่ามีผู้ใช้มากกว่าหนึ่งรายที่เข้าถึงทรัพยากรเดียวกัน ในสถานการณ์เช่นนี้ผู้ใช้รายหนึ่งพยายามแก้ไขทรัพยากรนั้นซึ่งทำให้เกิด 'ConcurrentProcessingException' เนื่องจากในกรณีนั้นผู้ใช้รายอื่นได้รับข้อมูลที่ไม่เหมาะสม ทั้งสองประเภทนี้เกี่ยวข้องกับสถานการณ์แบบนี้
พูดง่ายๆว่า
ล้มเหลวอย่างรวดเร็ว:
ล้มเหลวในความปลอดภัย :