Java Threads אליהו חלסצ'י תכנות מתקדם תרגול מספר 6

Slides:



Advertisements
Similar presentations
Ade Azurat, Advanced Programming 2004 (Based on LYS Stefanus’s slides) Advanced Programming 2004, Based on LYS Stefanus’s slides Slide 2.1 Multithreading.
Advertisements

Algorithm Programming Concurrent Programming in Java Bar-Ilan University תשס"ח Moshe Fresko.
Definitions Process – An executing program
Multithreading in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Threads Just Java: C10–pages 251- C11–pages 275-
Java Threads CS Introduction to Operating Systems.
Multithreading.
Parallel Processing (CS526) Spring 2012(Week 8).  Thread Status.  Synchronization in Shared Memory Programming(Java threads ) ◦ Locks ◦ Barriars.
A Bridge to Your First Computer Science Course Prof. H.E. Dunsmore Concurrent Programming Threads Synchronization.
EE2E1. JAVA Programming Lecture 8 Multi-threading.
1 CSCE3193: Programming Paradigms Nilanjan Banerjee Programming Paradigms University of Arkansas Fayetteville, AR
10/17/2015Vimal1 Threads By 10/17/2015Vimal2 Why use threads?? It is a powerful programming tool Computer users take it for granted.
Today’s Agenda  Quick Review  Finish Java Threads  The CS Problem Advanced Topics in Software Engineering 1.
Concurrent Programming in Java Dr. Zoltan Papp. Motivation: event driven, responsive systems Sequential approach: while ( true ) { do event = getEventId()
Processes & Threads Bahareh Goodarzi. Single & Multiple Thread of control code files data code files data.
Dr. R R DOCSIT, Dr BAMU. Basic Java : Multi Threading 2 Objectives of This Session State what is Multithreading. Describe the life cycle of Thread.
Threads Concurrency in Java. What is mult-tasking? Doing more than one task.
111 © 2002, Cisco Systems, Inc. All rights reserved.
Computer Engineering Rabie A. Ramadan Lecture 8. Agenda 2 Introduction Thread Applications Defining Threads Java Threads and States Priorities Accessing.
1 CMSC 341: Data Structures Nilanjan Banerjee Data Structures University of Maryland Baltimore County
Threads in Java. Processes and Threads Processes –A process has a self-contained execution environment. –Has complete set of runtime resources including.
1 Multithreaded Programming using Java Threads Prof. Rajkumar Buyya Cloud Computing and Distributed Systems (CLOUDS) Laboratory Dept. of Computer Science.
Synchronizing threads, thread pools, etc.
Multithreading in Java Sameer Singh Chauhan Lecturer, I. T. Dept., SVIT, Vasad.
Introduction to Threads Session 01 Java Simplified / Session 14 / 2 of 28 Objectives Define a thread Define multithreading List benefits of multithreading.
In Java processes are called threads. Additional threads are associated with objects. An application is associated with an initial thread via a static.
Multithreading in JAVA
Threading and Concurrency COM379T John Murray –
15.1 Threads and Multi- threading Understanding threads and multi-threading In general, modern computers perform one task at a time It is often.
Threads in Java1 Concurrency Synchronizing threads, thread pools, etc.
Concurrent Computing CSCI 201L Jeffrey Miller, Ph.D. HTTP :// WWW - SCF. USC. EDU /~ CSCI 201 USC CSCI 201L.
Multi-Threading in Java
Multithreaded programming  Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run.
Threads. Objectives You must be able to answer the following questions –What code does a thread execute? –What states can a thread be in? –How does a.
Threads in Java Threads Introduction: After completing this chapter, you will be able to code your own thread, control them efficiently without.
1 Java Programming Java Programming II Concurrent Programming: Threads ( I)
Multithreading. Multitasking The multitasking is the ability of single processor to perform more than one operation at the same time Once systems allowed.
Threads b A thread is a flow of control in a program. b The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
CSC CSC 143 Threads. CSC Introducing Threads  A thread is a flow of control within a program  A piece of code that runs on its own. The.
Advanced Tools for Multi- Threads Programming Avshalom Elmalech Eliahu Khalastchi 2010.
Concurrency in Java MD. ANISUR RAHMAN. slide 2 Concurrency  Multiprogramming  Single processor runs several programs at the same time  Each program.
CS203 Programming with Data Structures Introduction to Threads and Synchronization California State University, Los Angeles.
1 Multithreading in Java THETOPPERSWAY.COM. 2 Outline  Multithreading & Thread Introduction  Creating threads  Thread Life Cycle  Threads priorities.
SCJP 9/10 Threads.
Multithreading Lec 23.
Multi Threading.
Java Multithreading.
Lecture 9 Object Oriented Programming Using Java
Multithreading.
Java Concurrency.
Multithreading in Java
Section 5.7 Concurrency, Interference, and Synchronization.
Threads Chate Patanothai.
Definitions Concurrent program – Program that executes multiple instructions at the same time. Process – An executing program (the running JVM for Java.
Java Concurrency.
Multithreaded Programming in Java
Condition Variables and Producer/Consumer
Multithreading.
Condition Variables and Producer/Consumer
Multithreading 2 Lec 24.
Java Based Techhnology
Processes and Threads.
Multithreading.
Programming with Shared Memory Java Threads and Synchronization
برنامه‌نویسی چندنخی Multi-Thread Programming
class PrintOnetoTen { public static void main(String args[]) {
Java Thread.
Computer Science 2 06A-Java Multithreading
Threads CSE451 Andrew Whitaker TODO: print handouts for AspectRatio.
Java Chapter 3 (Estifanos Tilahun Mihret--Tech with Estif)
Presentation transcript:

Java Threads אליהו חלסצ'י תכנות מתקדם 89-210 תרגול מספר 6 תשס"ט 2009-2010 Java Threads אליהו חלסצ'י

האם המלבנים זזים בו זמנית ?

הקדמה הגדרה: thread (או תהליכון בעברית) הוא קטע יחיד ורציף של פעולות עם התחלה, רצף וסוף. מערכות הפעלה מודרניות מאפשרות לתהליך (process), להריץ מספר תהליכונים (threads) במרחב כתובות אחד. אנו יכולים לשנות קוד כך שירוץ בחלקים, ותיווצר תחושת מקביליות, אך הדבר כמובן מסורבל. כפיתרון שפת ה java מאפשרת לתכנת ב threads די בקלות – הקוד נכתב כרגיל ופשוט מורץ ב thread אחר.

על תהליכים ותהליכונים מערכת ההפעלה יכולה להריץ כמה תהליכים שונים במקביל, כל אחד במרחב כתובות משלו. בדרך כלל יש יותר תהליכים מאשר מעבדים (או ליבות) ולכן המעבד צריך לשלב בין התהליכים ברמה שתיראה לנו שהם רצים במקביל. (Time Slicing) לשם כך מתבצע מידי פעם מעבר במעבד מתהליך אחד לאחר, הפעולה נקראת Context Switch, היא יקרה מאד, ותלמדו על כל זאת ועוד בקורס מערכות הפעלה. יתרון בלתכנת בכמה תהליכים הוא לכאורה קבלת יותר משאבים ממערכת ההפעלה. יתרון אמיתי יותר הוא שאם תהליך נתקע, התוכנה כולה לא קורסת.

על תהליכים ותהליכונים כעת, כל תהליך שרץ במערת ההפעלה יכול להריץ כמה threads –תהליכונים. תהליכונים אלו הם חלקים שרצים "במקביל" כחלק מהתהליך עצמו ובמרחב הכתובות שלו. המשמעות שהתהליכונים שותפים לאותו מרחב כתובות היא שניתן בקלות להעביר מידע ביניהם. (יותר בקלות מאשר בין תהליכים) כמו כן, המעבר בין תהליכון אחד לשני אינו יקר כמו context switch בין תהליך אחד לשני. החיסרון הוא כמובן שיש לנו הקצאות זמן עיבוד של תהליך אחד.

Process 5 Process 6 Process 7 Process 8 Process 1 Process 2 Process 3 Operating System Context Switch Process 1 Process 2 Process 3 Process 4 thread1 thread2 thread1 thread2 VM thread3 ב VM ובמערוכת הפעלה מתקדמות ניתן אפילו להריץ threads שונים בליבות שונות אך כיום במערכות הסטנדרטיות אין אפילו ניצול מוחלט של הליבות לתהליכים.

למה צריך threads? יש אלגוריתמים מקביליים. I/O זו פעולה שלוקחת המון זמן מנקודת המבט של המעבד, למה לא לאפשר ריצה של דברים אחרים בינתיים? ביצוע משימות בלתי תלויות. Timers למיניהם. הכנה לסביבה מרובת מעבדים \ ליבות. עבודות שצריכות לרוץ ברקע, כמו gc.

יצירת threads כדי להריץ threads אנו צריכים להכיר את שני הדברים הבאים: הממשק Runnable המחלקה Thread שמממשת את Runnable. ל Runnable יש רק פונקציה אחת void run(); למחלקה Thread יש פונקציה מיוחדת start(); שהיא מריצה את run() בתהליכון נפרד, ומייד חוזרת – כלומר רצף התוכנית נמשך מייד לאחר הקריאה ל start(), ואין המתנה שהפעולה תסתיים. Runnable void run() Thread void run() void start()

יצירת threads הדרך ליצור תוכנית שתרוץ בthread נפרד: לרשת מ Thread לשכתב את הפונקציה run() שתעשה את הפעולות שנרצו שיקרו במקביל. לקרוא ל start(); class MyClass extends Thread { public void run() { קוד שירוץ במקביל... } … MyClass m = new MyClass() ; m.start() ; כדאי לשאול אותם, מה עוד לא בסדר בשיטה זו? ערבבנו בין ה"מה" וה"איך" בין ה Thread והלוגיקה של מה לבצע ולבין אופן הביצוע עצמו... שאלה: אבל מה אם המחלקה שלי צריכה לרשת כבר ממחלקה אחרת?

יצירת threads במקרה זה נצטרך: לממש את Runnable ליצור מופע חדש של המחלקה Thread עם המחלקה שלנו ב constructor לקרוא ל start(); class MyClass implements Runnable { public void run() { קוד שירוץ במקביל... } … MyClass m = new MyClass() ; Thread t = new Thread(m) ; t.start() ; שאלה: אבל מה קורה אם אנחנו לא רוצים לגעת במחלקה המקורית או לא יכולים?

יצירת threads נניח שיש לנו מחלקה C עם המתודה m שאנו לא רוצים \ יכולים לשנות בה כלום. אנו רוצים שהמתודה m תרוץ ב thread נפרד. נפתור זאת ע"י ירושה, או ע"י design pattern בשם Adapter. ע"י ירושה: class C { public void m() { …} } class RunnableC extends C implements Runnable { public void run() { m() ; } } RunnableC rc = new RunnableC() ; Thread t = new Thread(rc) ; t.start() ;

יצירת threads נניח שיש לנו מחלקה C עם המתודה m שאנו לא רוצים \ יכולים לשנות בה כלום. אנו רוצים שהמתודה m תרוץ ב thread נפרד. נפתור זאת ע"י ירושה, או ע"י design pattern בשם Adapter. ע"י Adapter: class C { public void m() { …} } class AdapterOfC implements Runnable { private C c ; public AdapterOfC(C c) { this.c = c ; } public void run() { c.m() ; } } C myC=new C(); AdapterOfC aoc = new AdapterOfC(myC) ; Thread t = new Thread(aoc) ; t.start() ;

מתודות שליטה ב threads start – מתחילה להריץ את run ב thread נפרד. sleep – ה thread נעצר עד שמתבצעת קריאה ל interrupt – עוצר את שנת ה thread. join – מחכה שה thread יסיים את עבודתו. קראנו ל t.start() שעושה את שלו. המשכנו לעשות דברים במקביל ל t. קריאה ל t.join() תגרום לנו לחכות ש t יסתיים. get/setPriority קביעת עדיפות הריצה של ה thread. yield - מאפשר ל threads אחרים בעלי אותה העדיפות זמן CPU על חשבונו. isAlive – האם ה thread עדיין לא סיים את עבודתו. Obj.wait() – גורם ל thread הנוכחי להמתין עד שthread אחר יקרא ל notify Obj.notify() – מעיר את אחד ה threads הממתינים.

מחזור החיים של thread born blocked פעולת synchronized או המתנה ל I/O סוף הסנכון או ה I/O running בחירה של ה scheduler born מצב ready בתור start() dead stop() run() סיים סוף ה time-slice או קריאה ל yield waiting notify() wait() sleeping sleep() interrupt()

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

הבעיה ב threads מה יהיה הפלט? לכאורה count גדל 100,000,000 פעמים ב 1 public class ThreadTest { static int count=0; private static class A implements Runnable{ public void run(){ for(int i=0;i<100000000;i++) count++; } public static void main(String[] args) { Thread t=new Thread(new A()); Thread t1=new Thread(new A()); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(count); מה יהיה הפלט? לכאורה count גדל 100,000,000 פעמים ב 1 בשני threads שונים ולכן התוצאה צריכה להיות 200,000,000... הפלט שיצא הפעם: 158,123,608 בעיה זו שייכת לבעיית הקטע הקריטי בפועל הפקודה count++ היא 3 פקודות שונות: טעינה מהזיכרון ערך לרגיסטר פעולה חשבונית על הרגיסטר שמירת הערך בזיכרון

סנכרון הפתרון לבעיה מושג ע"י סנכרון. המילה synchronized יכולה להופיע בכמה מקומות בקוד, ולאפשר גישה אקסקלוסיבית ל thread אחד בלבד באותו קטע קוד. כעת נשכלל את הדוגמא הקודמת: ניצור מחלקה כללית שתטפל בספירה. ניצור לה adapter שנוכל להכניס ל thread ושם נכניס את הלולאה ל 100,000,000 עדכונים

סנכרון על אובייקט עדיין לא סנכרנו דבר, ותוצאה לדוגמא היא : 131733427 public class ThreadTest { private static class CountAdapter implements Runnable{ Count c; public CountAdapter(Count c){ this.c=c; } public void run(){ for(int i=0;i<100000000;i++) c.update(); public static void main(String[] args) { Count c=new Count(); c.setCount(0); CountAdapter ca=new CountAdapter(c); Thread t=new Thread(ca); Thread t1=new Thread(ca); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(c.getCount()); public class Count { private int count; public void setCount(int x){count=x;} public int getCount(){return count;} public void update(){count++;} } עדיין לא סנכרנו דבר, ותוצאה לדוגמא היא : 131733427 הוספת synchronized על מתודה כלשהי תחסום את גישת האובייקט כולו ל threads אחרים עד שהמתודה תסתיים. שני threads על אותו האובייקט, מתאפשרת חלוקת מידע.

סנכרון על אובייקט public class ThreadTest { private static class CountAdapter implements Runnable{ Count c; public CountAdapter(Count c){ this.c=c; } public void run(){ for(int i=0;i<100000000;i++) c.update(); public static void main(String[] args) { Count c=new Count(); c.setCount(0); CountAdapter ca=new CountAdapter(c); Thread t=new Thread(ca); Thread t1=new Thread(ca); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(c.getCount()); public class Count { private int count; public void setCount(int x){count=x;} public int getCount(){return count;} public synchronized void update(){count++;} } הוספנו לפקודה update סנכרון והפעם התוכנית רצה מאד מאד לאט, מדוע? היכן יותר כדאי לשים את הסנכרון?

סנכרון על אובייקט עכשיו אכן התקבלה התוצאה הרצויה, public class ThreadTest { private static class CountAdapter implements Runnable{ Count c; public CountAdapter(Count c){ this.c=c; } public synchronized void run(){ for(int i=0;i<100000000;i++) c.update(); public static void main(String[] args) { Count c=new Count(); c.setCount(0); CountAdapter ca=new CountAdapter(c); Thread t=new Thread(ca); Thread t1=new Thread(ca); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(c.getCount()); public class Count { private int count; public void setCount(int x){count=x;} public int getCount(){return count;} public void update(){count++;} } עכשיו אכן התקבלה התוצאה הרצויה, אך האם שני ה threads אכן רצו במקביל? התשובה היא לא! רעיונות?

סנכרון על אובייקט עכשיו התקבלה התוצאה הרצויה, public class Count { private int count; public void setCount(int x){count=x;} public int getCount(){return count;} public void update(){count++;} } public class ThreadTest { private static class CountAdapter implements Runnable{ … public void run(){ for(int j=0;j<10000;j++) synchronized(c){ for(int i=0;i<10000;i++) c.update(); } public static void main(String[] args) { עכשיו התקבלה התוצאה הרצויה, גם יצרנו מקביליות בין 2 ה threads וגם התוכנית פעלה מהר!

סנכרון על מחלקה דוגמא חדשה, הפעם מפעילים את Count בצורה סטטית. public class Count { private static int count; public static void setCount(int x){count=x;} public static int getCount(){return count;} public static void update(){count++;} } public class ThreadTest { private static class CountRunnable implements Runnable{ public void run(){ for(int i=0;i<100000000;i++) Count.update(); } public static void main(String[] args) { CountRunnable ca=new CountRunnable(); Thread t=new Thread(ca); Thread t1=new Thread(ca); Count.setCount(0); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(Count.getCount()); דוגמא חדשה, הפעם מפעילים את Count בצורה סטטית. עדיין לא סנכרנו דבר, ותוצאה לדוגמא היא : 129400789

סנכרון על מחלקה public class Count { private static int count; public static void setCount(int x){count=x;} public static int getCount(){return count;} public static synchronized void update(){count++;} } public class ThreadTest { private static class CountRunnable implements Runnable{ public void run(){ for(int i=0;i<100000000;i++) Count.update(); } public static void main(String[] args) { CountRunnable ca=new CountRunnable(); Thread t=new Thread(ca); Thread t1=new Thread(ca); Count.setCount(0); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(Count.getCount()); אפשרות ראשונה, לשים synchronized על המתודה הסטטית, כל גישה סטטית תסונכרן. מה הבעיה באפשרות זו? מה נעשה הפעם כדי לפתור?

סנכרון על מחלקה נפצל את הלולאה כמו קודם, ונסנכרן הפעם את המחלקה public class Count { private static int count; public static void setCount(int x){count=x;} public static int getCount(){return count;} public static void update(){count++;} } public class ThreadTest { static int count=0; private static class CountRunnable implements Runnable{ public void run(){ for(int j=0;j<10000;j++) synchronized(Count.class){// or c.getClass() for(int i=0;i<10000;i++) Count.update(); } public static void main(String[] args) { CountRunnable ca=new CountRunnable(); Thread t=new Thread(ca); Thread t1=new Thread(ca); Count.setCount(0); t.start(); t1.start(); while(t.isAlive() || t1.isAlive()); System.out.println(Count.getCount()); נפצל את הלולאה כמו קודם, ונסנכרן הפעם את המחלקה ולא את האובייקט.

בשיעור הבא... נלמד על נושאים מתקדמים ב threads נלמד לתזמן משימות. נלמד על Java.Util.Concurrent. ועל מבני נתונים חסינים מבעיות ה threads.

הטמעה מה ההבדל בין Decorator ל Adapter? כאשר נוצר thread לאיזה תור הוא נכנס? מה מוציא אותו מהתור? מהו dead lock? תצרו שעון עצר (stopper) שיכול למדוד זמן בתחרות ריצה של 3 מתחרים. כשמגיע קלט enter מהמשתמש, ה thread נעצר והזמן שהוא רץ מוחזר.