Slide 1

מסמכים קשורים
Microsoft PowerPoint - 10_threads.ppt

PowerPoint Presentation

אוניברסיטת בן גוריון בנגב תאריך המבחן: שקולניק אלכסנדר שם המרצה: מר בשפת JAVA מבוא לתכנות מבחן ב: מס' הקורס : הנדסת תעשיה וניהול מ

מהוא לתכנות ב- JAVA מעבדה 3

הטכניון - מכון טכנולוגי לישראל הפקולטה להנדסת חשמל המעבדה למערכות תכנה מרושתות ניסוי בתכנות מקבילי ב- Java המאחר ביותר מ 51 דקות לא יורשה לבצע את הניס

אוניברסיטת בן גוריון בנגב תאריך המבחן: שם המרצה: מר אלכסנדר שקולניק, בשפת JAVA מבחן ב: מבוא לתכנות מס' הקורס : מיועד לתלמידי : הנד

מבוא למדעי המחשב

מבוא למדעי המחשב

מבוא למדעי המחשב

מבוא לתכנות ב- JAVA תרגול 11

Homework Dry 3

PowerPoint Presentation

תרגול 1

Slide 1

PowerPoint Presentation

תוכנה 1 תרגול מספר 12: GUI כתיבת מחלקות גנריות בית הספר למדעי המחשב אוניברסיטת תל אביב 1

מבוא למדעי המחשב

Microsoft PowerPoint - rec3.ppt

הגשה תוך שבוע בשעת התרגול

Slide 1

מבוא למדעי המחשב

פתרון מוצע לבחינת מה"ט ב_שפת c מועד ב אביב תשע"ט, אפריל 2019 מחברת: גב' זהבה לביא, מכללת אורט רחובות שאלה מספר 1 מוגדרת מחרוזת המורכבת מהספרות 0 עד 9.

מבחן 7002 פרטים כלליים מועד הבחינה: בכל זמן מספר השאלון: 1 משך הבחינה: 3 שעות חומר עזר בשימוש: הכל )ספרים ומחברות( המלצות: קרא המלצות לפני הבחינה ובדי

Slide 1

PowerPoint Presentation

PowerPoint Presentation

Slide 1

תרגול מס' 4: המתרגם שימוש במחלקות קיימות מחרוזות, קבצים, וקבלת קלט מהמשתמש

סדנת תכנות ב C/C++

מקביליות

מבוא לתכנות ב- JAVA תרגול 7

שאלהIgal : מערכים דו מימדיים רקורסיה:

תכנות מונחה עצמים א' – תש"ע

תרגול 1

BIG DATA תיאור הקורס המונח Big Data הולך וצובר תאוצה בשנים האחרונות, הוא הופך למגמה רווחת בתעשייה. המשמעות הפרקטית של המונח Big Data הינה טכנולוגיות נ

Microsoft PowerPoint - lec10.ppt

Microsoft Word - pitaron222Java_2007.doc

משימה תכנית המתרגמת קטעי טקסט לשפה אחרת הקלט: קובץ המכיל את קטעי הטקסט וכן את השפה אליה רוצים לתרגם תרגול מס' 4: המתרגם שימוש במחלקות קיימות תכנות מתק

שבוע 4 סינטקס של HACK ASSEMBLY ניתן להשתמש בשלושה אוגרים בלבד:,A,D,M כולם בעלי 16 ביטים. M אינו אוגר ישיר- הוא מסמן את האוגר של ה RAM שאנחנו מצביעים ע

PowerPoint Presentation

Slide 1

Microsoft Word B

מבחן סוף סמסטר מועד ב 28/10/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, גדי אלכסנדרוביץ הוראות: א. בטופס המבחן 6 עמודים (כולל דף זה) ו

תרגול 1

מקביליות

בחן במערכות הפעלה

מבחן סוף סמסטר מועד א 15/02/08 מרצה אחראית: דר שירלי הלוי גינסברג מתרגלים: גלעד קותיאל, דניאל גנקין הוראות: א. בטופס המבחן 7 עמודים ו 4 דפי נוסחאות. ב

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

PowerPoint Presentation

Slide 1

מספר מחברת: עמוד 1 מתוך 11 ת"ז: תשע"א מועד ב סמסטר א' תאריך: 00:11 שעה: 0 שעות הבחינה: משך כל חומר עזר אסור בשימוש בחינה בקורס: מבוא למדעי ה

מתכונת עיצוב 3013

תרגול 1

מקביליות

תורת הקומפילציה

PowerPoint Presentation

שאלהIgal : מערכים דו מימדיים רקורסיה:

מבוא למדעי המחשב, סמסטר א', תשס"ח תרגול מס' 2

PowerPoint Presentation

PowerPoint Presentation

Microsoft PowerPoint - rec1.ppt

Slide 1

PowerPoint Presentation

Microsoft PowerPoint - lec2.ppt

לנץ קרן מרצה: תכנותמונחהעצמים) ( יוםשישי 15 אוקטובר 0202 ב מועד 0202, אביב סמסטר סמסטר סוף מבחן גוטמן אייל רביב, אריאל משנה, אלון מתרגלים: הנחי

אוניברסיטת חיפה החוג למדעי המחשב מבוא למדעי המחשב מועד א' סמסטר ב', תשע"ג, משך המבחן: שעתיים וחצי חומר עזר: אסור הנחיות: וודאו כי יש בידיכם

מבוא למדעי המחשב

מצגת של PowerPoint

Slide 1

מבוא לאסמבלי

Slide 1

פייתון

מבוא למדעי המחשב - חובלים

1

Microsoft PowerPoint - lec9.ppt

Microsoft Word - c_SimA_MoedB2005.doc

איטרטורים: 1 תוכנה 1 סתיו תשע"ג תרגיל מספר 9 הנחיות כלליות: קראו בעיון את קובץ נהלי הגשת התרגילים אשר נמצא באתר הקורס. הגשת התרגיל תעשה במערכת ה moodl

אוניברסיטת חיפה החוג למדעי המחשב מרצה: שולי וינטנר מתרגלים: נעמה טוויטו, מחמוד שריף מבוא למדעי המחשב סמסטר א' תשע"ב בחינת סיום, מועד א', הנחי

Microsoft PowerPoint - T-10.ppt [Compatibility Mode]

Slide 1

Slide 1

תרגול 3 - מערכים

Microsoft PowerPoint - rec8.ppt

Microsoft PowerPoint - lec9.ppt

תוכנה 1 בשפת Java שיעור מספר 3: "חתיכת טיפוס"

תוכן העניינים

שאלהIgal : מערכים דו מימדיים רקורסיה:

PowerPoint Presentation

המשימה תרגול מס' 5: קלט-פלט במערכות הפעלה שונות יש סימונים שונים עבור ירידת שורה :)newline( ב- UNIX/Linux )Line Feed( \n ב- Windows )Carriage Return +

HTML - Hipper Text Makeup Language

יוםראשון, 02 ליולי 2014 סמסטר סוף מבחן )236703( עצמים מונחה תכנות - א' מועד 2014, אביב סמסטר קמחי יחיאל ד"ר מרצה: מסינג מיטל עבדאלקאדר, כרם גלעד, ערן

תמליל:

פיתוח מערכות תוכנה מבוססות Java מקביליות אוהד ברזילי

מקביליות רמת התהליך )multithreading( ההפעלה processes( )multi לעומת רמת מערכת ריבוי מעבדים processors( )multi זמן עיבוד slicing( )time לעומת חלוקת 2

חוטים תהליך )process( הוא הפשטה של מחשב וירטואלי חוט context( )execution thread, execution הוא הפשטה מעבד וירטואלי אנו מבדילים בין: CPU, Code, Data 3

חוטים עד עכשיו ראינו כי שני שרותים אינם רצים ביחד כאשר שרות קורא לשרות אחר, מצביע התוכנית "קופץ" לשרות האחר וכאשר הוא מסיים הוא חוזר לשרות הקורא למשל אם ב main מופיעה קריאה ל ()f ביצוע main נעצר והוא ממשיך רק אחרי סיום ()f main() call f() f() זמן main() 4

חוטים לעומת זאת אם main יריץ את ()f main ו- ()f ימשיכו במקביל )!( בחוט נפרד ריצות זמן main() בשפת :C createthread) f)( ( main() f() בהקשרים מסוימים אומרים כי ()f מתבצעת א-סינכרונית לפונקציה main() 5

למה חוטים? הנדסת תוכנה: מודלריות, הכמסה שימוש יעיל במשאבים חישוב מבוזר משימות אופיניות: Non blocking I/O Timers משימות בלתי תלויות אלגוריתמים מקביליים ומבוזרים דברים ש"רצים ברקע" Collection( )Garbage 6

חשוב לזכור לשימוש בחוטים יש תקורה והוא אינו בהכרח משפר את ריצת התוכנית! מעבד אחד יכול לבצע לכל היותר פעולה אחת בו זמנית כאשר בתוכנית יש מרכיב I/O דומיננטי השימוש בחוטים עשוי להשתלם 7

Performance Issues Synchronization is expensive! Comparison table (in time units): Non-synchronized method Synchronized method Single thread accessing the methods n threads accessing simultaneously 1 ~3 1 ~3*n 8

Performance Issues Thread creation and start are expensive! Comparison table (in time units): Creating a String 1 Creating a Thread ~10 Creating a Thread and starting it ~200 (!) 9

חוטים ב- Java כמו כל דבר ב-,Java מופע של המחלקה Thread גם חוט ב Java הוא עצם חוט תמיד מריץ מתודה עם חתימה קבועה: main() public void run() חוץ מהחוט הראשי שמריץ את מחלקה שמממשת את run() Runnable בעצם מממשת את המנשק כלומר, חוט ב Java הוא מופע של המחלקה Thread שהועבר לו כארגומט )למשל בבנאי( עצם ממחלקה שהיא implements Runnable 10

public class ThreadTester { public static void main(string args[]) { HelloRunner r = new HelloRunner(); Thread t = new Thread(r); t.start(); // do other things... class HelloRunner implements Runnable { int i; קריאה ישירות ל run תריץ אותה בצורה סינכרונית! public void run() { i = 0; while (true) { System.out.println("Hello " + i++); if (i == 50) { break; 11

מה ההבדל בין 2 התוכניות הבאות? public class TwoThreadTester1 { public static void main(string args[]) { HelloRunner r1 = new HelloRunner(); HelloRunner r2 = new HelloRunner(); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); public class TwoThreadTester2 { public static void main(string args[]) { HelloRunner r = new HelloRunner(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); 12

שיתוף מידע ההבחנה עדינה על אותו עצם Runnable יכולים לרוץ במקביל 2 חוטים הדבר מאפשר לשני החוטים לחלוק מידע בינהם public class TwoThreadTester { public static void main(string args[]) { HelloRunner r = new HelloRunner(); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); מה יודפס? כדי להבין טוב יותר מי מדפיס מה, נוסיף פרטים להדפסה 13

public class TwoThreadTesterId { public static void main(string args[]) { HelloRunnerId r = new HelloRunnerId(); Thread t1 = new Thread(r, "first"); Thread t2 = new Thread(r, "second"); t1.start(); t2.start(); class HelloRunnerId implements Runnable { int i; public void run() { i = 0; while (true) { System.out.println( Thread.currentThread().getName() + ": Hello " + i++); if (i == 50) break; 14

מחזור החיים של חוט )חלקי( 15

חסימת חוט public class Runner implements Runnable { public void run() { while (true) { // do lots of interesting stuff //... // Give other threads a chance try { Thread.sleep(10); catch (InterruptedException e) { // This thread s sleep was // interrupted by another thread שיטה זו מחליפה את השימוש ב- suspend ו- resume שהתגלו כבעיתיות והוכרזו deprecated 16

סיום חוט public class Runner2 implements Runnable { private boolean timetoquit = false; public void run() { while (!timetoquit) { // continue doing work // clean up before run() ends public void stoprunning() { timetoquit = true; 17

סיום חוט public class ThreadController { private Runner2 r = new Runner2(); private Thread t = new Thread(r); public void startthread() { t.start(); public void stopthread() { // use specific instance of Runner r.stoprunning(); שיטה זו מחליפה את השימוש ב- stop runfinalizersonexit שהתגלו 18 כבעיתיות והוכרזו deprecated ו-

מתודות מיושנות המאמר המלא: http://java.sun.com/j2se/1.5.0/docs/guide/misc/threadprimitivedeprecation.html 19

עבודה עם חוטים isinterrupted(), שאילתות: isalive() interrupted() עדיפות ריצה: getpriority() setpriority() )static( )static( חסימת חוט Thread.sleep() join() Thread.yield() 20

שימוש ב join public static void main(string[] args) { Thread t = new Thread(new Runner()); t.start(); //... // Do stuff in parallel with the other thread for a while //... // Wait here for the other thread to finish try { t.join(); catch (InterruptedException e) { // the other thread came back early // Now continue in this thread //... 21

ירושה מ Thread public class MyThread extends Thread { public void run() { while (true) { // do lots of interesting stuff try { Thread.sleep(100); catch (InterruptedException e) { // sleep interrupted public static void main(string args[]) { Thread t = new MyThread(); t.start(); 22

ירושה לעומת הכלה המחלקה Thread עצמה היא Runnable ולכן ניתן לרשת ממנה, לדרוס את run() ולקבל בקלות מחלקה שהיא גם חוט עצמאי להכלה יתרונות מתודולוגיים כגון: עיצוב נקי התאמה לירושה יחידה עיקביות עם ספריות אחרות ירושה ממחישה את הערוב )השגוי בדרך כלל( שבין הלוגיקה העסקית שיש לבצע והאופן שבו יש לבצע אותה )ה'מה' וה'איך'( 23

שימוש ב synchronized public class MyStack { int idx = 0; char[] data = new char[6]; public void push(char c) { data[idx] = c; idx++; public char pop() { idx--; return data[idx]; ננסה לתאר תרחישים שבהם עבודה עם המחלקה לא תצליח בתוכנית מרובת חוטים הפעולות push ו- pop צריכות להתבצע ללא הפרעה יש לבצע אותן כפעולות אטומיות כדי לשמור על עקביות מבנה הנתונים 24

מנעול לעצמים Java מספקת לכל עצם )במחלקה )Object מנעול פרטי אנלוגיה: מפתח יחיד לשימוש בשרותים ציבוריים כאשר מספר חוטים רצים על אותו העצם יכול אחד מהם לקחת את המפתח לעצמו ובכך לחסום את ריצת האחרים public void push(char c) { synchronized (this) { data[idx] = c; idx++; 25

מנעול לעצמים Java מספקת לכל עצם )במחלקה )Object מנעול פרטי אנלוגיה: מפתח יחיד לשימוש בשרותים ציבוריים כאשר מספר חוטים רצים על אותו העצם יכול אחד מהם לקחת את המפתח לעצמו ובכך לחסום את ריצת האחרים public void push(char c) { synchronized (this) { data[idx] = c; idx++; 26

מנעול לעצמים כאשר מגיע חוט אחר לאותו קטע קוד, המנעול חסר, והחוט מחכה לחזרתו public void push(char c) {? synchronized (this) { data[idx] = c; idx++; שחרור המנעול מתבצע אוטומטית ביציאה מבלוק :synchronized אחרי סיום הבלוק אחרי break, return, throw מתוך הבלוק 27

עקביות בשימוש במנעולים כדי שהמנגנון יעבוד יש לסנכרן את כל הגישות לנתונים המשותפים מתוך pop וגם מתוך )push )גם יש להגן על נתונים משותפים רגישים ע"י private אחרת קוד לקוד יוכל לשנות אותם בצורה לא מסונכרנת public void push(char c) { synchronized (this) { // The push method code שני קטעי הקוד הבא שקולים: public synchronized void push(char c) { // The push method code 28

מחזור החיים של חוט )חלקי( 29

מבוי סתום )deadlock( כאשר שני חוטים ממתנים כל אחד למנעול המוחזק אצל האחר )משאב( קשה לזהות או להימנע מכך במקרה הכללי, ואולם שמירה על כמה כללים פשוטים ימנעו זאת ברוב המקרים: החלטה על סדר נעילה קבוע אכיפת הסדר לאורך התוכנית שחרור המנעולים בסדר הפוך 30

תקשורת בין חוטים notify( )wait & אנלוגיה: נהג המונית והנוסע לצורך מימוש הרעיון מספקת :Java את המתודות wait ו- notify הגדרת wait pool מאחורי הקלעים( נוסף על ה lock pool )הממומשים - השימוש במתודות wait synchronized context ו- notify הוא מתוך 31

מחזור החיים של חוט 32

דוגמת הצרכן-יצרן public class Producer implements Runnable { private SyncStack thestack; private int num; private static int counter = 1; public Producer (SyncStack s) { thestack = s; num = counter++; 33

לוגיקת היצרן public void run() { char c; for (int i = 0; i < 200; i++) { c = (char)(math.random() * 26 +'A'); thestack.push(c); System.out.println("Producer" + num + ": " + c); try { Thread.sleep((int)(Math.random() * 300)); catch (InterruptedException e) { // ignore it // END run method // END Producer class 34

הצרכן public class Consumer implements Runnable { private SyncStack thestack; private int num; private static int counter = 1; public Consumer (SyncStack s) { thestack = s; num = counter++; 35

לוגיקת הצרכן public void run() { char c; for (int i = 0; i < 200; i++) { c = thestack.pop(); System.out.println("Consumer" + num + ": " + c); try { Thread.sleep((int)(Math.random() * 300)); catch (InterruptedException e) { // ignore it // END run method // END Consumer class 36

המחסנית public class SyncStack { private List<Character> buffer = new ArrayList<Character>(400); public synchronized char pop() { //... public synchronized void push(char c) { //... איך נכתוב את המתודות pop ו- push כך שישמר העיקרון שפעולת pop ממתינה לכך שיהיה איבר במחסנית? 37

pop() public synchronized char pop() { char c; while (buffer.size() == 0) { try { this.wait(); catch (InterruptedException e) { // ignore it... c = buffer.remove(buffer.size() - 1); return c; אובייקט המחסנית עצמו מגלם ארוע לוגי "StackNotEmpty" הארוע לא מופיע בקוד בצורה מפורשת והמתכנתת צריכה לשמור על עיקביותו 38

push() public synchronized void push(char c) { this.notify(); buffer.add(c); המתודה push מבטיחה )ע"פ תנאי האחר של החוזה שלה( כי בסיומה המחסנית אינה ריקה על כן המחסנית מודיעה )notify( לאחד המעוניינים בארוע )אם קיים כזה( שהארוע התרחש אם יש יותר מממתין אחד לארוע, תודיע מערכת ההפעלה רק לאחד הממתינים על התרחשותו אם יש צורך להודיע לכולם ניתן להשתמש במתודה notifyall() 39

2 יצרנים, 2 צרכנים public class SyncTest { public static void main(string[] args) { SyncStack stack = new SyncStack(); Producer p1 = new Producer(stack); Thread prodt1 = new Thread (p1); prodt1.start(); Producer p2 = new Producer(stack); Thread prodt2 = new Thread (p2); prodt2.start(); Consumer c1 = new Consumer(stack); Thread const1 = new Thread (c1); const1.start(); Consumer c2 = new Consumer(stack); Thread const2 = new Thread (c2); const2.start(); 40

נושאים מתקדמים בעבודה עם חוטים מבוסס על פרק 5.7 ב- Java in a Nutshell 5 th edition By David Flanagan

תזמון משימות בעזרת המחלקות ו- Executor נותן לתזמן בקלות משימות דחויות ומשימות חוזרות Timer // Define the time-display task TimerTask displaytime = new TimerTask() { public void run() { System.out.printf("%tr%n", System.currentTimeMillis()); ; // Create a timer object to run the task (and possibly others) Timer timer = new Timer(); // Now schedule that task to be run every 1,000 milliseconds, // starting now timer.schedule(displaytime, 0, 1000); // To stop the time-display task displaytime.cancel(); 42

Executor ב Java5 הוגדרה הספריה java.util.concurrent להחביא את האופן שבו מבוצעת הלוגיקה אשר מספקת כלים למשל: מבני נתונים א-סינכרונים כגון BlockingQueue המנשק Executor העוטף את טיפוס ה Runnable /** Execute a Runnable in the current thread. */ class CurrentThreadExecutor implements Executor { public void execute(runnable r) { r.run(); /** Execute each Runnable using a newly created thread */ class NewThreadExecutor implements Executor { public void execute(runnable r) { new Thread(r).start(); 43

/** * Queue up the Runnables and execute them in order using a single thread * created for that purpose. */ class SingleThreadExecutor extends Thread implements Executor { BlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>(); public void execute(runnable r) { // Don't execute the Runnable here; just put it on the queue. // Our queue is effectively unbounded, so this should never block. // Since it never blocks, it should never throw InterruptedException. try { q.put(r); catch(interruptedexception never) { throw new AssertionError(never); // This is the body of the thread that actually executes the Runnables public void run() { for(;;) { // Loop forever try { Runnable r = q.take(); // Get next Runnable, or wait r.run(); // Run it! catch(interruptedexception e) { // If interrupted, stop executing queued Runnables. return; 44

ThreadPoolExecutor בפועל אין אפילו צורך לממש בעצמנו Executors java.util.concurrent מספקת חזק וגמיש הספריה ThreadPoolExecutor ניתן לעבוד איתו בעזרת מחלקת המפעל :Executors Executor onethread = Executors.newSingleThreadExecutor(); // pool size of 1 Executor fixedpool = Executors.newFixedThreadPool(10); // 10 threads in pool Executor unboundedpool = Executors.newCachedThreadPool(); // as many as needed או ליצור אותו בצורה מפורשת )כדי להגדיר את מאפיניו( 45

אין שכל אין דאגות היכולת לא לדעת את אופן הביצוע של משימה בעת הגדרת המשימה היא רעיון מפתח בהנדסת תוכנה הדבר: מפשט את הקוד מכליל את הקוד )ניתן להשתמש באותו הקוד גם עבור משימות סינכרוניות וגם עבור משימות א-סינכרוניות( משפר את המודולריות של המערכת 46

Callable, ExecutorService יורש מ Executor ויודע לטפל גם בטיפוס המנשק ExecutorService Callable call מכיל מתודה אחת בשם Runnable בדומה ל Callable השרות call של Callable בשונה מ- :Runnable יכול להחזיר ערך יכול לזרוק חריג מה המשמעות של החזרת ערך משרות שאולי מתבצע א-סינכרונית? קריאה ישירות ל call תבצע אותו בצורה סינכרונית קריאה ל submit תבצע אותו בצורה א-סינכרונית מה יקרה בינתיים למי שקרא ל?submit האם הוא?blocked זה הרי סותר את כל רעיון ה א-סינכרוניות! 47

בחזרה לעתיד השרות call מחזיר ערך מטיפוס Future<T> שעליו ניתן להפעיל את המתודות: isdone() cancel() iscanceled() get() הקריאה היא blocked השרות עשוי לזרוק חריג ExecutionException 48

import java.util.concurrent.*; import java.math.biginteger; import java.util.random; import java.security.securerandom; דוגמא /** This is a Callable implementation for computing big primes. */ public class RandomPrimeSearch implements Callable<BigInteger> { static Random prng = new SecureRandom(); // self-seeding int n; public RandomPrimeSearch(int bitsize) { n = bitsize; public BigInteger call() { return BigInteger.probablePrime(n, prng);... // Try to compute two primes at the same time ExecutorService threadpool = Executors.newFixedThreadPool(2); Future<BigInteger> p = threadpool.submit(new RandomPrimeSearch(512)); Future<BigInteger> q = threadpool.submit(new RandomPrimeSearch(512)); BigInteger product = p.get().multiply(q.get()); 49

Putting it all together הטיפוס ScheduledExecutorService משלב את תכונות ה Callable ו- Runnable עם הרצת טיפוסי Timer ניתן להגדיר טיפוסי ScheduledFuture השהייה עם מחזוריות ו\או Executors מתודות Factory מתאימות מסופקות במחלקה עבודה עם Future היא העבודה עם callback גישה תכנותית מתחרה לגישת 50

עידון מנגנוני הסנכרון בגרסאות Java הראשונות )לפני )Java5 לא ניתן לגשת ישירות למנעולים, אלא רק דרך בלוק synchronized בתחילה היה נראה שהדבר מפשט את מנגנון התזמון כשם ש Java בחרה להפקיע את ניהול הזיכרון מהמשתמש אולם התגלה כי יש אלגוריתמי סינכרון שלא ניתן לממש כאשר הנעילה היא block-scoped החבילה java.util.concurrent.locks מגדירה מבנים המחזירים למתכנתת את הכח שנגזל ממנה 51

דוגמא import java.util.concurrent.locks.*; // New in Java 5.0 /** * A partial implementation of a linked list of values of type E. * It demonstrates hand-over-hand locking with Lock */ public class LinkList<E> { E value; // The value of this node of the list LinkList<E> rest; // The rest of the list Lock lock; // A lock for this node public LinkList(E value) { // Constructor for a list this.value = value; // Node value rest = null; // This is the only node in the list lock = new ReentrantLock(); // We can lock this node 52

/** * Append a node to the end of the list, traversing the list using * hand-over-hand locking. This method is threadsafe: multiple threads * may traverse different portions of the list at the same time. **/ public void append(e value) { LinkList<E> node = this; // Start at this node node.lock.lock(); // Lock it. // Loop 'till we find the last node in the list while(node.rest!= null) { LinkList<E> next = node.rest; // This is the hand-over-hand part. Lock the next node and then // unlock the current node. We use a try/finally construct so // that the current node is unlocked even if the lock on the // next node fails with an exception. try { next.lock.lock(); // lock the next node finally { node.lock.unlock(); // unlock the current node node = next; // At this point, node is the final node in the list, and we have // a lock on it. Use a try/finally to ensure that we unlock it. try { node.rest = new LinkList<E>(value); // Append new node finally { node.lock.unlock(); 53

מנגנוני תזמון נוספים Semaphore acquire() release() tryaquire() CountDownLatch await() countdown() Exchanger exchange() CyclicBarrier await() (Reentrant) ReadWriteLock read() write() 54

מבני נתונים מסונכרנים מימושי Set, List, and Map ב java.util אינם )Vector,Hashtable ל )פרט synchronized כאשר עובדים עם כמה חוטים ניתן לעטוף אותם בטיפוסים מסונכרנים: List synclist = Collections.synchronizedList(list); Map syncmap = Collections.synchronizedMap(map); )עם הפעולות put() ו- ב Java5 התווספו 5 מימושים למנשק Queue :)take() ArrayBlockingQueue LinkedBlockingQueue PriorityBlockingQueue DelayQueue SynchronousQueue 55

פעולות אטומיות java.util.concurrent.atomic מספקת בחבילה Java טיפוסים בעלי פעולות אטומיות מובנות כגון compareandset ו- getandincrement import java.util.concurrent.atomic.atomicinteger; // The count1(), count2() and count3() methods are all threadsafe. Two // threads can call these methods at the same time, and they will never // see the same return value. public class Counters { // A counter using a synchronized method and locking int count1 = 0; public synchronized int count1() { return count1++; 56

AtomicInteger // A counter using an atomic increment on an AtomicInteger AtomicInteger count2 = new AtomicInteger(0); public int count2() { return count2.getandincrement(); // An optimistic counter using compareandset() AtomicInteger count3 = new AtomicInteger(0); public int count3() { // Get the counter value with get() and set it with compareandset(). // If compareandset() returns false, try again until we get // through the loop without interference. int result; do { result = count3.get(); while (!count3.compareandset(result, result + 1)); return result; 57

יצירת אנימציה ניתן להשתמש בחוטים כדי ליצור אנימציה ציור סדרת תמונות עם המתנה בין תמונה לתמונה public class AnimationBounce { private static final int IMAGE_WIDTH = 100; private static final int TIMER_INTERVAL = 10; private static int x = 0; private static int y = 0; private static int directionx = 1; private static int directiony = 1; private static Canvas canvas; public static void animate() {... public static void main(string[] args) {... 58

public static void main(string[] args) { final Display display = new Display(); final Shell shell = new Shell(display); shell.settext("animator"); shell.setlayout(new FillLayout()); canvas = new Canvas(shell, SWT.NO_BACKGROUND); canvas.addpaintlistener(new PaintListener() { public void paintcontrol(paintevent event) { // Draw the background event.gc.fillrectangle(canvas.getbounds()); event.gc.setbackground(shell.getdisplay().getsystemcolor(swt.color_red)); event.gc.filloval(x, y, IMAGE_WIDTH, IMAGE_WIDTH); ); shell.open(); Runnable runnable = new Runnable() { public void run() { animate(); display.timerexec(timer_interval, this); ; display.timerexec(timer_interval, runnable); while (!shell.isdisposed()) { if (!display.readanddispatch()) { display.sleep(); // Kill the timer display.timerexec(-1, runnable); display.dispose(); 59

animate() public static void animate() { x += directionx; y += directiony; // Determine out of bounds Rectangle rect = canvas.getclientarea(); if (x < 0) { x = 0; directionx = 1; else if (x > rect.width - IMAGE_WIDTH) { x = rect.width - IMAGE_WIDTH; directionx = -1; if (y < 0) { y = 0; directiony = 1; else if (y > rect.height - IMAGE_WIDTH) { y = rect.height - IMAGE_WIDTH; directiony = -1; // Force a redraw canvas.redraw(); 60

Flickering בעיית ההבהוב במימוש היא בעיה חוזרת היא נובעת מהעובדה כי בכל עדכון של התמונה אנו מציירים את כל המסך מחדש הציור מתחיל מציור הרקע על כל המסך, אגב מחיקת הכדור הציור כולל גם ציור מיותר של חלקים שאין צורך לעדכן ניתן להתמודד עם הבעיה בשתי אסטרטגיות עדכון של האזור הדינאמי בלבד )clipping( עדכון של התמונה כולה מאחורי הקלעים Buffering( )Double 61

Double Buffering public void paintcontrol(paintevent event) { // Create the image to fill the canvas Image image = new Image(shell.getDisplay(), canvas.getbounds()); // Set up the offscreen gc GC gcimage = new GC(image); gcimage.setbackground(event.gc.getbackground()); gcimage.fillrectangle(image.getbounds()); gcimage.setbackground(shell.getdisplay().getsystemcolor(swt.color_red)); gcimage.filloval(x, y, IMAGE_WIDTH, IMAGE_WIDTH); // Draw the offscreen buffer to the screen event.gc.drawimage(image, 0, 0); ); image.dispose(); gcimage.dispose(); 62

ניהול המקביליות ע"י סביבת העבודה קיימים מקרים שבהם לא נרצה להתעסק בסוגית המקביליות כלל מקרים?( )אילו ספריות ומסגרות עבודה מנהלות את ענייני המקבילות "מאחורי הקלעים" דוגמאות: ספריית המנשק הגרפי Swing שרתי אינטרנט )כדגומת )Tomcat בחלק מהמקרים המקבילות "דולפת" לאפליקציה בעקבות באגים או בעקבות שימוש במחלקות שאינן בטוחות לשימוש בסביבות מרובות חוטים 63

עבודה עם מחלקות בטוחות קיימות כמה מחלקות אשר ידועות כ thread safe מחלקות אלו אוכפות בעזרת מבני synchronize שלמות המידע ואחרים את לבטיחות זו יש מחיר בביצועים ולכן הוגדרו לאותן מחלקות גם גרסאות קלילות יותר לשימוש בישומי single thread לדוגמא: StringBuilder ומקבילתה StringBuffer ArrayList ומקבילתה Vector 64