מצב ה thread
thread של ג'אווה נמצא תמיד באחד ממספר מצבים:
המצב שלו מציין מה הוא עושה ברגע נתון ומה הוא מסוגל לעשות באותו הזמן.
לדוגמא יתכן שהוא ירוץ, יישן, לא יפעל וכו'…
הספר “The Java Totorial" מאת Campione & Walrath ,בדומה לספרים טובים רבים אחרים, נותנים דיאגרמות שעוזרות להמחיש את המצבים השונים של הthread .
אני ממליץ לעבור על אחד או שניים מהספרים האלה ולהבין את הדיאגרמות שהם מציגים. (נכון לזמן בו נכתבים דברים אלה, 2/1/97, אפשר להשיג מספר ספרי ג'אווה טובים ברשת באתרים כמו: JavaSoft , Same Publishing, Que Publishing, וקרוב לוודאי שגם באחרים ).
בדיאגרמה שהם מציגים בע"מ 25 מציינים Campione & Walrath ש thread יכול להיות בכל אחד מהמצבים הבאים:
· thread חדש (New Thread)
· ניתן להרצה (Runnable)
· לא ניתן להרצה (Not Runnable)
· מת/לא פועל (Dead)
הם מדגישים כי הדיאגרמה שלהם גם מדגימה אילו קריאות למתודות גורמות מעבר למצב אחר:
והם קובעים: " הדיאגרמה הזו אינה דיאגרמת המצבים המוחלטת אלא מעין מבט כללי על ההיבטים היותר מעניינים ושכיחים של חיי ה- thread."
Thread חדש
יצירת מופעים לאובייקט של Thread יוצרת thread חדש אך לא מריצה אותו. זה המצב אותו הם מכנים New Thread . בתוכנית הנ"ל שלנו, הייתה הקביעה של יצירת המופעים כדלהלן:
Thread myThreadA = new Thread(new MyThread(),"threadA"); |
במילים אחרות, Cmapione & Walrath אומרים לנו שכש threadנמצא במצב זה אתה רק יכול להפעיל (start) או לעצור אותו. כל מתודה אחרת מלבד start() או stop() גורמת
ל IllegalThreadStateException.
ניתן להרצה Runnable))
Campione & Walrath אומרים לנו שהפעלת מתודת start() על אובייקט של Thread
- יוצרת את משאבי המערכת הנחוצים להרצת הthread
- קובעת מתי ירוץ ה- thread
- קוראת למתודה run()של ה thread
זה מציב את ה thread במצב שאותו הם מכנים "המצב הניתן להרצה"((the Runnable state.
הם נזהרים להגדיר אותו כמצב ניתן להרצה ולא כמורץ בפועל, מכיוון שייתכן שהthread למעשה לא יפעל/ירוץ כשהוא במצב הזה (ייתכן כי הוא לא ינצח בתחרות על משאבי המחשב).
מכיוון שלחלק גדול מהמחשבים יש מעבד בודד שלא מאפשר להריץ את כל הthreads הניתנים להרצה בו זמנית, מערכת זמן-הריצה(runtime system) של ג'אווה קובעת מסגרת זמנים שבאמצעותה יכולים כל ה threads הניתנים להרצה להתחלק במעבד.
thread ניתן להרצה יכול לרוץ למעשה או להיות בהמתנה לתורו לרוץ.
לא ניתן להרצה
לפי Campione & Walrath , thread הופך ל לא-ניתן-להרצה כשמתרחש אחד המצבים הבאים:
· מישהו מפעיל את מתודת שלו sleep()
· מישהו מפעיל את מתודת שלו suspend()
· ה thread משתמש במתודת wait() שלו לחכות ל condition variable
(אותו נסביר מאוחר יותר).
· ה thread נחסם בגלל ה I/O (קלט/פלט).
כבר ראית מספר דוגמאות כיצד מביאים thread למצב כזה
באמצעות הפעלת מתודת ה sleep() שלו.
להלן אחת מהן:
Thread.currentThread().sleep(1000); |
במקרה הספציפי הזה, המתודהrun() 'הרדימה' את עצמה למשך שניה אחת ונעשתה בלתי ניתנת
להרצה בפרק זמן זה. במשך פרק הזמן הזה, לא ירוץ ה thread אפילו אם המעבד פנוי, אפשר
'להעיר' thread על ידי הפעלת המתודה interrupt() על אובייקט ה thread הישן.
אחרת הוא לא יתעורר עד שיעבור זמן השינה הקבוע- בסופה של ההפסקה הקבועה, ה thread הופך
שוב לניתן להרצה באופן אוטומטי.
השאלה האם הוא ירוץ בפועל או לא, תלויה במקום שלו בסולם העדיפויות, ובזמינות של המעבד.
לפי Campion & Walrath "לכל אחת מהכניסות למצב הבלתי- ניתן- להרצה יש נתיב יציאה ספציפי נפרד המחזיר את הthread למצב הניתן-להרצה מחדש. נתיב היציאה מתאים רק לכניסה התואמת שלו. לדוגמא, אם ה thread עבר למצב שינה, אז המספר הנקוב באלפיות השנייה צריך לחלוף לפני שה thread הופך שוב להיות ניתן להרצה. לקריאה ל resume() במצב של thread ישן אין כל השפעה." |
Campione & Walrath נותנים את רשימת הכניסות הבאה
ל "בלתי ניתן להרצה" (Not Runnable) ואת נתיב היציאה התואם.
- אם thread הועבר למצב שינה, חייב לחלוף המס' הנקוב באלפיות שניה (או שהוא ייקטע הכרח).
-אם thread הושעה (suspended) אז מישהו חייב לקרוא למתודת ה resume() שלו.
- אם thread מחכה למשתנה תנאי, האובייקט שבבעלותו נמצא המשתנה, יהא אשר יהא, חייב
לוותר עליו על ידי קריאה ל notify() או notifyAll() .
- אם thread נחסם ב I/O , ה I/Oחייב להסתיים.
מת (Dead)
ממש כמו המקבילה האנושית שלו, ה thread יכול 'למות' בשתי דרכים:
-מגורמים טבעיים או
-כשהורגים אותו (עוצרים אותו).
Campione &Walrath אומרים לנו ש thread מת באופן טבעי
כשמתודת ה run() שלו יוצאת (exits) בצורה רגילה.
אתה גם יכול תמיד 'להרוג' thread באמצעות קריאה למתודת ה stop() שלו.
המינוח המעניין הבא מגיע מ Campione & Walrath : "המתודה stop() משליכה אובייקט ThreadDeath על הthread כדי להרוג אותו. לכן, כש thread נהרג באופן הזה, הוא מת באופן בלתי מסונכרן. ה thread ימות כשהוא יקבל למעשה את חריגת ה ThreadDeath."
בשיעור על טיפול
בחריגות בו נאמר שלפי הספר “Java in a Nutshell" ("ג'אווה בתמצית") מאת David Flangan,
ה- ThreadDeath נובע למעשה מהמחלקה Error ולא מהמחלקה Exeption.
Flanganאומר לנו: " שגיאה מסמלת באופן כללי שהתרחשה שגיאה בלתי ניתנת לתיקון.
הן לא צריכות להיתפס, ובד"כ גורמות לאינטרפרטר של ג'אווה להציג מסר exit.
ה- ThreadDeath error יוצאת מכלל זה כי היא גורמת ל thread שבו היא מושלכת להפסיק
לרוץ/לפעול, אך היא לא מדפיסה מסר error או משפיעה על threads אחרים."
Threads שנדמה כי הם מסרבים למות
קיוויתי כי עד עכשיו (ינואר 1998), JDK 1.0.2 כבר לא תהיה בשימוש.
בכל אופן, מאחר והדפדפנים ממשיכים לפגר מאחור ביכולת התמיכה שלהם ל- JDK 1.1 זה לא מה
שקרה.
כשהשתמשתי ב JDK 1.0.2 נתקלתי בבעיה מוזרה כשעשיתי קומפילציה והרצה לתוכניות עם
threads תוך שימוש ב JDK 1.0.2 בתיבת DOS בחלונות 95.
בפרט, העובדה שכמהthreads סירבו למות. לכל הפחות, הם סירבו להחזיר את השליטה למערכת
ההפעלה כשהם כן מתו. למרבה המזל, בעיה זו נפתרה ב- JDK 1.1.1.
IllegalThreadstateException
מערכת זמן-הריצה run-time system) ) זורקת IllegalThreadStateException כשאתה קורא
למתודה בthread והמצב של הthread לא מתיר קריאת מתודה זאת.
בדומה לכל החריגות "נבדקו" כשאתה קורא למתודה של thread שיכולה לזרוק חריגה,
עתה, עליך לתפוס (catch) את החריגה.
זה מודגם בקריאות למתודה sleep() בתוכניות ההדגמה שהבאנו.
isAlive המתודה
המחלקהThread כוללת מתודה המכונה isAlive(). היא מחזירהtrue אם הthread הופעל ולא
נעצר (ניתן-להרצה runnable= ,או לא-ניתן-להרצה= not runnable לפי תיאור המצבים הקודם).
12-10-03 / 21:25 עודכן , 11-10-03 / 11:33 נוצר ע"י רונית רייכמן בתאריך