ריבוי תהליכים MultiThrading דוגמת הרצה מהו תהליך? הדגמת הפיצול דוגמאות לתהליכים gc,main, applet, מוזיקה וסרטים. 2 שיטות לניהול תהליכים תלוי במעה"פ סדר עדיפויות solaris )אפשרות להרעבה( חלון זמן Windows אין כל כך משמעות לעדיפויות התהליכים. מודל הקומות נסיון של java לניהול עדיפויות. מחזור החיים של תהליך שגי ה
המחלקה Thread קבועי המחלקה 10 = Thread.MAX_PRIORITY Thread.NORM_PRIORITY = 5 Thread.MIN_PRIORITY = 1 מטודות המחלקה Thread() Thread(String threadname) run() IllegalThreadStateException start() InterruptedException סטטית sleep(long milliseconds)????? - interrupt)( interrupted)( סטטית -?????????? - isinterrupted)( dead ועד הגיעו למצב הופעל מרגע ש- start true מחזיר isalive() curremtthread() סטטית מחזירה reference לתהליך שכרגע רץ. join() ממתין לסיום thread אחר לפני המשך ביצועו של ה- thread הנוכחי. yeald() מאפשר ל- thread אחר לרוץ. )נכנס ה- thread בעדיפות הגבוהה ביותר(. wait() נכנס למתן המתנה על גבי אובייקט מסויים. notify() מעיר תהליך בהמתנה. notifyall() מעיר את כל התהליכים הממתינים. setpriority(int priority) getpriority() setname(string threadname) getname() tostring() שם ה- thread, עדיפות והקבוצה אליה שייך. דוגמא. public class HelloThread extends Thread { כתיבת Thread 1. ע"י ירושה מהמחלקה.Thread public void run() { System.out.println("Hello from a thread!"); public class TestThread { public static void main(string[] args){ HelloThread ht1 = new HelloThread(); HelloThread ht2 = new HelloThread(); ht1.start(); ht2.start(); ע"י מימוש הממשק.Runnable דוגמא. public class HelloRunnable implements Runnable {.2 public void run() { System.out.println("Hello from a thread!"); public class TestRunnable { public static void main(string[] args){ Thread t1 = new Thread(new HelloRunnable()); Thread t2 = new Thread(new HelloRunnable()); t1.start(); t2.start();
Synchronized סנכרון תהליכים מחסנית בייצוג מערך. הוספת איבר למחסנית: 1. הוספת איבר, 2: עדכון האינדקס. הבעיה: התהליך שמוסיף איבר למחסנחית מ בד את ה- cpu ל חר הוספת האיבר ולפני עדכון האינדקס. תהליך שני בא להוציא איבר מהמחסנית... Synchronized בא לפתור בעיה זו. לכל אובייקט יש מנעול. כאשר תהליך כלשהו נכנס לאיזור synchronized הוא לוקח את המנעול לידיו ואף תהליך אחר לא יכול להיכנס לאיזור זה עד שהתהליך שחרר את המנעול. בעיות בסנכרון תהליכחם לא ניתן להבטיח שתהליכים יתבצעו בסדר הרצוי. לא ניתן להבטיח שקטע קריטי לא יקטע באמצע ביצועו. מטודה מסונכרנת מבטיח מניעה הדדית בביצוע המטודה שני תהליכים לא יכולים לבצא את אותה מטודה בו זמנית תהליכים אחרים יושהו עד סיום הביצוע בסיום הביצוע ע"י תהליך מסויים תהליך אחר יורשה לבצע את המטודה. תהליך המבצע מטודה מסונכרנת "נועל" את ה ובייקט אליו שייכת המטודה. שום תהליך אחר לא יוכל לבצע בזמן זה מטודה מסונכרנת אחרת של אובייקט זה..monitor אובייקט מסוג זה ניקרא..monitor רק תהליך אחד רשאי לבצע מטודה מסונכרנת של אובייקט.monitor הגדרה זו מאפשרת לאותו תהליך לבצע יותר ממטודה אחת של אובייקט מטודה אחת קוראת למטודה אחרת o התנהגות זו מאפשרת למנוע מצב "קיפ ון" deadlock של תהליך בודד. o דוגמ בעמוד 161 נעילת מטודות לא מאפשר לגשת לאף מטודה אחרת של האובייקט כשתהליך מסוים נמצא כבר במטודה מסוימת של אותו אובייקט. public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; public synchronized void decrement() { c--; public synchronized int value() { return c;
מ) נעילה ע"י מנעול נעילה ע"י מנעול מאפשרת להגדיר קטעי קוד נעולים ולא נעילה של מטודות שלמות. public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; public void inc2() { synchronized(lock2) { c2++; ו- notify Wait קבוצת הנכנסים קבוצת המחכים קבוצת הנכנסים תהליך המבקש לבצע מטודה מסונכרנת של מוניטור כשהוא "נעול". ברגע שהמוניטור מתפנה תהליך כלשהוא אקראי נבחר וממשיך את הביצוע מהמקום שהופסק. קבוצת המחכים במהלך ביצוע של מטודה מסונכרנת התהליך מזהה שהוא חייב להמתין שפעולה אחרת תסתיים. במיקרה זה הוא משהה את עצמו ע"י קריאה למטודה wait() )Object- Wait התהליך מושהה ומשוייך לקבוצת המחכים השייכת למוניטור בו הוא מתבצע. התהליך עובר למצב Ready והמוניטור מתפנה "לטפל" בתהליכים אחרים )הנכנסים( Notify/NotifyAll התהליך שקרא למטודה wait ממתין עד אשר תהליך אחר המבצע מטודה מסונכרנת באותו מוניטור יקרא למטודה notify או.notifyAll קריאה ל- notify תהליך אחד מקבוצת המחכים נבחר באופן אקראי ומועבר לקבוצת הנכנסים. )במידה וקבוצת המחכים ריקה לא יקרה כלום(. קריאה ל- notifyall התהליך שקרא ל- notify ממשיך להתבצע כרגיל עד שמשחרר את המוניטור. כשהמוניטור מתפנה תהליך כלשהו מקבוצת הנכנסים נבחר אקראית ומתבצע. כל התהליכים בקבוצת המחכים מועברים לקבוצת הנכנסים. )במידה והקבוצה ריקה לא יקרה כלום( התהליך שקרא ל- notifyall ממשיך להתבצע עד שמשחרר את המוניטור. כשהמוניטור משוחרר אחת מקבוצת הנכנסים נבחר אקראית להמשך ביצוע. הערות ניתן לקרוא למטודות הנ"ל מתוך מטודות מסונכרנות בלבד מטודות אלה מוגדרות במחלקה Object ולא במחקה Thread אם תהליך מקבוצת המחכים מקבל פסיקה "זורק".)checked( InterruptedException ניתן לקרוא ל-( mili wait(long הדבר גורם להשהיית התהליך עד לסיום הזמן או קריאה ל- notyfy. המוקדם מביניהם. התהליך עובר מקבוצת המחכים לקבוצת הנכנסים.
דוגמ לסנכרון ב מצעות wait/notify // A correct implementation of a producer and consumer. public class Q { int n; boolean valueset = false; public synchronized int get() { if(!valueset) try { wait(); catch(interruptedexception e) { System.out.println("InterruptedException caught"); System.out.println("Got: " + n); valueset = false; notify(); return n; public synchronized void put(int n) { if(valueset) try { wait(); catch(interruptedexception e) { System.out.println("InterruptedException caught"); this.n = n; valueset = true; System.out.println("Put: " + n); notify();
public class Producer implements Runnable { private Q q; public Producer(Q q) { this.q = q; new Thread(this, "Producer").start(); public void run() { int i = 0; while(true) { q.put(i++); public class Consumer implements Runnable { private Q q; public Consumer(Q q) { this.q = q; new Thread(this, "Consumer").start(); public void run() { while(true) { q.get(); public class PCFixed { public static void main(string args[]) { private Q q = new Q(); new Producer(q); new Consumer(q); System.out.println("Press Control-C to stop.");
דוגמא מעמוד 154 דוגמא מעמוד 163 במיקרה זה הוגדרה מחלקה Controller המשמשת כמתווך בין תהליך main לתהליכים האחרים. הבנאי מקבל פרמטר המייצן את כמות התהליכים להם יש להמתין. המטודה finished מקדמת מוהנ המייצג את מספר התהליכים שהסתיימו. כאשר התהליך האחרון מסיים הוא מעיר )notify( את התהליך שביצע wait על המוניטור. המטודה waitforthreads נקראת ע"י תהליך main לצורך המתנה לתהליכים האחרים. תהליך main מכניס את עצמו ל- wait כל עוד כל התהליכים האחרים לא סיימו. כאשר הוא מתעורר )notify( בודק שוב את התנאי וחוזר לביצוע ה- main. השתמשנו ב- notify כי ידוע שרק תהליך אחד ממתין. במקרים אחרים רצוי לקרוא ל- notifyall כי לא ניתן לבחור את התהליך אותו רוצים לעיר לכן רצוי להעיר את כולם ולהרדים חזרה את מי שלא אמור להתעורר. הבדיקה ב- waitforthreads נעשית בלולאה ולא ב- if. הלולאה גורמת לתהליך שהתעורר לבדוק את התנאי שוב לפני שהוא ממשיך. הלולאה מתאימה בעיקר למצבים שהרבה תהליכים הממתינים לאותו מוניטור. כשהתהליכים מתעוררים עליהם לוודא שבאמת הם היו אמורים להתעורר ושהתנאי תקף. הערות
תהליכים מסוג Daemon בד"כ מספקים שרותים לתהליכיים אחרים. המטודה run שלהם בדרך כלל בלולאה אין-סופית. תכנית מרובת תהליכים מסתיימת כשכל התהליכים שאינם daemon מסתיימים. תהליכים מסוג daemon הינם בעלי עדיפות נמוכה ביותר. מגדיר תהליך כ- Deamon. setdaemon(true).deamon לבדוק אם תהליך הוא isdaemon()