מדריך CopyOnWriteArrayList

1. סקירה כללית

במאמר מהיר זה, נבחן את ה- CopyOnWriteArrayList מ ה java.util.concurrent חֲבִילָה.

זהו קונסטרוקציה שימושית מאוד בתוכניות מרובות הליכי משנה - כאשר אנו רוצים לחזור על רשימה בצורה בטוחה לשרשור ללא סנכרון מפורש.

2. CopyOnWriteArrayList ממשק API

העיצוב של CopyOnWriteArrayList משתמש בטכניקה מעניינת כדי להפוך אותה לבטוחה בחוטים ללא צורך בסנכרון. כאשר אנו משתמשים באחת משיטות השינוי - כגון לְהוֹסִיף() אוֹ הסר () - את כל התוכן של CopyOnWriteArrayList מועתק לעותק הפנימי החדש.

בשל עובדה פשוטה זו, אנו יכולים לחזור על הרשימה בצורה בטוחה, גם כאשר מתרחש שינוי במקביל.

כשאנחנו מתקשרים ל איטרטור () שיטה על CopyOnWriteArrayList, אנחנו חוזרים איטרטור מגובה בתמונת המצב הבלתי ניתנת לשינוי של תוכן ה- CopyOnWriteArrayList.

התוכן שלה הוא העתק מדויק של נתונים שנמצאים בתוך רשימת מערך מהתקופה שבה ה- איטרטור נוצר. גם אם בינתיים שרשור אחר מוסיף או מסיר אלמנט מהרשימה, שינוי זה הוא יצירת עותק חדש של הנתונים שישמשו בכל בדיקת נתונים נוספת מאותה רשימה.

המאפיינים של מבנה נתונים זה הופכים אותו לשימושי במיוחד במקרים בהם אנו חוזרים על זה לעיתים קרובות יותר מאשר אנו משנים אותו. אם הוספת אלמנטים היא פעולה נפוצה בתרחיש שלנו, אז CopyOnWriteArrayList לא תהיה בחירה טובה - מכיוון שהעותקים הנוספים בהחלט יובילו לביצועים תת-פרתיים.

3. התבוסס CopyOnWriteArrayList תוך כדי הכניסה

בואו נגיד שאנחנו יוצרים מופע של ה- CopyOnWriteArrayList המאחסן מספרים שלמים:

מספרי CopyOnWriteArrayList = חדש CopyOnWriteArrayList (מספר שלם חדש [] {1, 3, 5, 8});

לאחר מכן, אנו רוצים לחזור על מערך זה, ולכן אנו יוצרים איטרטור למשל:

איטרטור איטרטור = numbers.iterator ();

לאחר איטרטור נוצר, אנו מוסיפים אלמנט חדש ל- מספרים רשימה:

numbers.add (10);

זכור שכאשר אנו יוצרים איטרטר עבור ה- CopyOnWriteArrayList, אנו מקבלים תמונת מצב בלתי ניתנת לשינוי של הנתונים ברשימה באותו זמן איטרטור () נקרא.

בגלל זה, תוך כדי איטרציה על זה, לא נראה את המספר 10 באיטרציה:

תוצאת רשימה = קישור רשימה חדשה (); iterator.forEachRemaining (תוצאה :: הוסף); assertThat (תוצאה). מכיל רק (1, 3, 5, 8);

איטרציה עוקבת באמצעות חדש שנוצר איטרטור יחזיר גם את המספר 10 שנוסף:

איטרטור איטרטור 2 = numbers.iterator (); רשימת תוצאות 2 = רשימת קישורים חדשה (); iterator2.forEachRemaining (result2 :: add); assertThat (תוצאה 2). מכיל רק (1, 3, 5, 8, 10);

4. אסור להסיר בזמן איטרציה

ה CopyOnWriteArrayList נוצר כדי לאפשר אפשרות של איטרציה בטוחה על פני אלמנטים גם כאשר הרשימה הבסיסית משתנה.

בגלל מנגנון ההעתקה, ה- לְהַסִיר() מבצע על השיבה איטרטור אינו מותר - וכתוצאה מכך לא נתמךOperationException:

@Test (צפוי = UnsupportedOperationException.class) חלל ציבורי כאשרIterateOverItAndTryToRemoveElement_thenShouldThrowException () {CopyOnWriteArrayList numbers = New CopyOnWriteArrayList (שלם חדש [] {1, 3, 5, 8} איטרטור איטרטור = numbers.iterator (); בעוד (iterator.hasNext ()) {iterator.remove (); }}

5. מסקנה

במדריך מהיר זה, הסתכלנו על CopyOnWriteArrayList יישום מה java.util.concurrent חֲבִילָה.

ראינו את הסמנטיקה המעניינת של רשימה זו וכיצד ניתן לאתר אותה בצורה בטוחה לשרשור, בעוד שרשורים אחרים יכולים להמשיך להכניס או להסיר ממנה אלמנטים.

ניתן למצוא את היישום של כל הדוגמאות וקטעי הקוד בפרויקט GitHub - זהו פרויקט Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.