שיטת Thread.join () בג'אווה

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

במדריך זה נדון בשונה לְהִצְטַרֵף() שיטות ב פְּתִיל מעמד. ניכנס לפרטים של שיטות אלה וקוד לדוגמא.

כמו לַחֲכוֹת() ו להודיע ​​על שיטות (), לְהִצְטַרֵף() הוא מנגנון נוסף של סנכרון בין חוטים.

אתה יכול להעיף מבט מהיר במדריך זה כדי לקרוא עוד על לַחֲכוֹת() ו לְהוֹדִיעַ().

2. ה Thread.join () שיטה

שיטת ההצטרפות מוגדרת ב פְּתִיל מעמד:

צירוף הריק הסופי הציבורי () זורק את InterruptedException

מחכה שהחוט הזה ימות.

כאשר אנו קוראים את לְהִצְטַרֵף() בשיטה על חוט, חוט הקריאה עובר למצב המתנה. הוא נשאר במצב המתנה עד לסיום החוט המפנה.

אנו יכולים לראות התנהגות זו בקוד הבא:

class SampleThread מרחיב אשכול {public int processingCount = 0; SampleThread (int processingCount) {this.processingCount = processingCount; LOGGER.info ("הנושא נוצר"); } @Override הפעלה בטלנית ציבורית () {LOGGER.info ("אשכול" + this.getName () + "התחיל"); תוך כדי (processingCount> 0) {נסה {Thread.sleep (1000); } לתפוס (InterruptedException e) {LOGGER.info ("אשכול" + this.getName () + "הופרע"); } עיבוד מספר -; } LOGGER.info ("אשכול" + this.getName () + "יוצא"); }} @ מבט חלל ציבורי givenStartedThread_whenJoinCalled_waitsTillCompletion () זורק InterruptedException {Thread t2 = SampleThread new (1); t2.start (); LOGGER.info ("הפעלת הצטרפות"); t2.join (); LOGGER.info ("הוחזר מהצטרפות"); assertFalse (t2.isAlive ()); } 

עלינו לצפות לתוצאות דומות לבאות בעת ביצוע הקוד:

מידע: חוט נוצר מידע: קריאה להצטרפות מידע: חוט משנה -1 התחיל מידע: חוט משנה 1 יוצא מידע: הוחזר מהצטרפות

ה לְהִצְטַרֵף() השיטה עשויה לחזור גם אם החוט המפנה הופרע. במקרה זה, השיטה זורקת חריג מופרע.

סוף כל סוף, אם השרשור שהופנה כבר הסתיים או לא התחיל, הקריאה ל לְהִצְטַרֵף() השיטה חוזרת מיד.

חוט t1 = SampleThread חדש (0); t1.join (); // חוזר מיד

3. Thread.join () שיטות עם פסק זמן

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

ישנן שתי גרסאות מתוזמנות המעמיסות את ה- לְהִצְטַרֵף() שיטה:

"הצטרפות חלל סופית ציבורית (ארוכה מיליס) זורק את InterruptedException

מחכה לכל היותר מיליס אלפיות השנייה כדי שהשרשור הזה ימות. פסק זמן של 0 פירושו לחכות לנצח. "

"הצטרפות חלל סופית ציבורית (ארוכה מיליס, אינטננו) זורק את InterruptedException

מחכה לכל היותר מיליס אלפיות השנייה פלוס ננו ננו שניות כדי שהשרשור הזה ימות. ”

אנחנו יכולים להשתמש בתזמון המתוזמן לְהִצְטַרֵף() כלהלן:

@Test ציבורי בטל givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout () זורק InterruptedException {Thread t3 = SampleThread new (10); t3.start (); t3.join (1000); assertTrue (t3.isAlive ()); } 

במקרה זה, הברגה המתקשרת ממתינה לשנייה בערך עד לסיום החוט t3. אם החוט t3 לא מסתיים בפרק זמן זה, לְהִצְטַרֵף() השיטה מחזירה את השליטה לשיטת הקריאה.

מתוזמן לְהִצְטַרֵף() תלוי במערכת ההפעלה לתזמון. לכן, איננו יכולים להניח זאת לְהִצְטַרֵף() יחכה בדיוק כמה שצוין.

4. Thread.join () שיטות וסנכרון

בנוסף לחכות לסיום, להתקשר אל לְהִצְטַרֵף() לשיטה יש אפקט סינכרון. להצטרף () יוצר קשר שקורה לפני:

"כל הפעולות בשרשור מתרחשות לפני שכל שרשור אחר חוזר בהצלחה מ- join () בשרשור זה."

פירוש הדבר שכאשר חוט t1 קורא t2.join (), אז כל השינויים שנעשו על ידי t2 נראים ב- t1 בתמורה. עם זאת, אם איננו קוראים לְהִצְטַרֵף() או להשתמש במנגנוני סינכרון אחרים, אין לנו שום ערובה לכך ששינויים בשרשור השני יהיו גלויים לשרשור הנוכחי, גם אם השרשור השני הושלם.

מכאן, למרות שה- לְהִצְטַרֵף() שיטת קריאה לשרשור במצב שהסתיים חוזרת מיד, אנחנו עדיין צריכים לקרוא לזה במצבים מסוימים.

אנו יכולים לראות דוגמה לקוד מסונכרן בצורה לא נכונה להלן:

SampleThread t4 = SampleThread חדש (10); t4.start (); // לא מובטח שיעצור גם אם t4 מסתיים. לעשות {} תוך (t4.processingCount> 0);

כדי לסנכרן כראוי את הקוד הנ"ל, אנו יכולים להוסיף מתוזמן t4.join () בתוך הלולאה או השתמש במנגנון סנכרון אחר.

5. מסקנה

לְהִצְטַרֵף() השיטה שימושית למדי לסנכרון בין חוטים. במאמר זה דנו ב לְהִצְטַרֵף() שיטות והתנהגותן. בדקנו גם קוד באמצעות לְהִצְטַרֵף() שיטה.

כמו תמיד, ניתן למצוא את קוד המקור המלא ב- GitHub.