נושאים מתקדמים ב Threads

Download Report

Transcript נושאים מתקדמים ב Threads

‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
‫‪Executor‬‬
‫‪ThreadPools‬‬
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
‫‪ 89-210‬תכנות מתקדם ‪ -‬תרגול ‪6‬‬
‫תכנות מתקדם ‪89-210‬‬
‫תרגול מספר ‪6‬‬
‫תשע"א ‪2010-2011‬‬
‫נושאים מתקדמים ב ‪Threads‬‬
‫אליהו חלסצ'י‬
‫‪ 89-210‬תכנות מתקדם ‪ -‬תרגול ‪6‬‬
‫הקדמה‬
‫•‬
‫•‬
‫•‬
‫•‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
‫‪Executor‬‬
‫‪ThreadPools‬‬
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
‫בשיעור הקודם למדנו על אופן פעולת ה ‪ thrads‬ב ‪,java‬‬
‫ואיך להריץ אותם ברמה בסיסית‬
‫השיטות בהן השתמשנו מתאימות למשימות פשוטות‪ ,‬אך‬
‫למשימות מורכבות יותר נדרש ‪ ,Higher-Level API‬כזה‬
‫שיסתיר לנו את הלוגיקה מאחורי ניהול ה ‪ ,threads‬ויוכל‬
‫לבצע משימות מתקדמות יותר‬
‫הוא נחוץ אף יותר עבור אפליקציות כבדות שמנצלות‬
‫באופן מלא את המערכות מרובות המעבדים \ ליבות‬
‫המצויות כיום‬
‫בגרסא ‪ ,5‬נכנס ‪ java.util.concurrent‬עליו נלמד היום‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
‫תזמון משימות‬
public class ThreadTest {
private static class Ping implements Runnable{
public void run(){while(true)System.out.println("ping");}
}
private static class Pong implements Runnable{
public void run(){while(true)System.out.println("pong");}
}
public static void main(String[] args) {
Ping ping=new Ping();
Pong pong=new Pong();
Thread t=new Thread(ping,"thread 1");
Thread t1=new Thread(pong,"thread 2");
t.start();
t1.start();
}
}
‫מחלקה אחת תמיד כותבת‬
pong ‫ והשנייה תמיד‬ping
ping ‫אנו רוצים להתחיל מ‬
‫ושהשניים יתחלפו בכל חצי‬
.‫שנייה‬
‫כרגע הם נכתבים לא לפי‬
‫הסדר ולא לא לפי הקצב‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
‫תזמון משימות‬
wait() ‫דוגמא עם‬
public class Player implements Runnable{
private String hit;// ping or pong
Object lock;
Object obj=new Object();
public Player(String hit,Object o) {
Thread t1=new Thread(new Player("ping",obj));
this.hit=hit;
Thread t2=new Thread(new Player("pong",obj));
lock=o;
t1.start();
}
t2.start();
@Override
public void run() {
synchronized (lock) {
while(true){
System.out.println(hit);
lock.notify();
try {
lock.wait();
}catch (InterruptedException e) {}
}}}}
Causer Output
t1
t2
t1 
t2 
t1 
t2 
t1 
…
wait
notify
wait
notify
wait
notify
wait
notify
wait
notify
ping
pong
ping
pong
ping
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
‫תזמון משימות‬
public class ThreadTest {
private static class Ping implements Runnable{
public void run(){
while(true){
System.out.println("ping");
try {Thread.sleep(1000);}
‫ניתן גם לפתור את הבעיה‬
‫ למשך‬sleep ‫באמצעות‬
‫ ולהתחיל את ה‬,‫שנייה‬
‫ בהפרש של‬Threads
‫חצי שנייה‬
‫הפיתרון כמובן מסורבל‬
catch (InterruptedException e) {}
}
public static void main(String[] args) throws
InterruptedException {
}
Ping ping=new Ping();
}
Pong pong=new Pong();
private static class Pong implements Runnable{
Thread t=new Thread(ping,"thread 1");
public void run(){
Thread t1=new Thread(pong,"thread 2");
while(true){
System.out.println("pong");
t.start();
try {Thread.sleep(1000);}
long time2,time=System.currentTimeMillis();
catch (InterruptedException e) {}
while((time2=System.currentTimeMillis())-time<500);
t1.start();
}
}
}
}
}
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
‫תזמון משימות‬
import java.util.Timer;
import java.util.TimerTask;
public class ThreadTest {
private static class Ping extends TimerTask{
public void run(){System.out.println("ping");}
}
private static class Pong extends TimerTask{
public void run(){System.out.println("pong");}
}
public static void main(String[] args){
Ping ping=new Ping();
Pong pong=new Pong();
Timer t=new Timer();
t.scheduleAtFixedRate(ping, 0, 1000);
t.scheduleAtFixedRate(pong, 500, 1000);
}
}
‫ יכולה לבצע את כל‬Timer ‫המחלקה‬
‫ההתאמות הדרושות מאחורי הקלעים‬
‫ שרץ ברקע‬thread ‫ולתזמן משימות ב‬
‫ניתן לבטל משימות ע"י קריאה ל‬
‫ ימשיך לרוץ‬timer ‫ אך ה‬cancel()
‫ עצמו ע"י‬timer ‫ניתן לבטל את ה‬
‫ שלו‬cancel() ‫קריאה ל‬
int i;
while((i=System.in.read())!=13);
ping.cancel(); ‫ בוטל‬ping ‫ ממשיך‬t
pong.cancel(); ‫ בוטל‬pong ‫ ממשיך‬t
t.cancel(); ‫ בוטל‬t
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
‫דוגמת סנכרון משיעור קודם‬
public class ThreadTest {
private static class CountAdapter implements Runnable{
public class Count {
Count c;
private int count;
public CountAdapter(Count c){
public void setCount(int x){count=x;}
public int getCount(){return count;}
this.c=c;
}
public void run(){
for(int i=0;i<100000000;i++)
c.update();
public synchronized void
update(){count++;}
}
}
}
‫שיעור קודם שחקנו עם מיקום הסנכרון‬
‫והגענו לפשרה בין מקביליות למהירות‬
public static void main(String[] args) {
Count c=new Count();
c.setCount(0);
CountAdapter ca=new CountAdapter(c);
‫בדוגמא אפשרנו מקביליות על חשבון‬
...‫מהירות ריצה‬
‫ שניות‬46 ‫זמן הריצה היה כ‬
Thread t=new Thread(ca);
Thread t1=new Thread(ca);
long time=System.currentTimeMillis();
t.start();
t1.start();
‫כעת נשתמש במשתנה אטומי‬
while(t.isAlive() || t1.isAlive());
System.out.println(c.getCount());
System.out.println((System.currentTimeMillis()-time)/1000);
}}
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
‫משתנים אטומיים‬
public class ThreadTest {
private static class CountAdapter implements Runnable{
import java.util.concurrent.atomic.AtomicInteger;
Count c;
public CountAdapter(Count c){
public class Count {
this.c=c;
private AtomicInteger count=new AtomicInteger(0);
}
public
public void run(){
void setCount(int x){count.set(x);}
public int getCount(){return count.get();}
for(int i=0;i<100000000;i++)
c.update();
public void update(){
}
count.incrementAndGet();// count++
}
}
public static void main(String[] args) {
}
Count c=new Count();
c.setCount(0);
‫הפעם השתמשנו באובייקט‬
‫ אחד‬thread ‫ – רק‬AtomicInteger
.‫יכול לבצע עליו פעולות‬
CountAdapter ca=new CountAdapter(c);
Thread t=new Thread(ca);
Thread t1=new Thread(ca);
long time=System.currentTimeMillis();
t.start();
.‫ שניות‬6 ‫זמן הריצה היה כ‬
t1.start();
while(t.isAlive() || t1.isAlive());
System.out.println(c.getCount());
System.out.println((System.currentTimeMillis()-time)/1000);
}}
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
deadlock ‫דוגמא ל‬
public class Friend {
‫נתון הפרוטוקול הבא‬
‫ אם אחד המשתתפים אומר‬:"‫לפתיחת "דייט‬
"‫"הא" האחר צריך להשיב "דה‬
threads ‫ החיים ב‬Bob ‫ ו‬Alice ,‫בדוגמא‬
"‫ יצאו ל"דייט‬,‫נפרדים‬
"‫• שניהם מתפרצים ואומרים "הא‬
‫ האובייקטים‬,"‫• בגלל הסנכרון על אמירת ה"הא‬
"‫ נעולים עד שאמירת ה"הא‬Bob ‫ ושל‬Alice ‫של‬
‫תסתיים‬
‫• אמירת ה"הא" לא מסתיימת עד שהאחר‬
"‫יאמר "דה‬
‫ ואם‬,"‫• אבל יש גם סנכרון על אמירת ה"דה‬
‫ השני לא יכול‬Thread ‫ ה‬,‫האובייקט נעול‬
‫להיכנס אליו‬
‫ תקועים בשתיקה מביכה‬Bob ‫ ו‬Alice •
private String name;
public Friend(String name){this.name = name;}
public String getName(){return this.name;}
public synchronized void sayHA(Friend date) {
System.out.format("%s says HA to %s%n",this.name, date.getName());
date.sayDA(this);
}
public synchronized void sayDA(Friend date) {
System.out.format("%s says DA to %s%n",this.name,date.getName());
}
}
public class DeadLock {
private static class FriendRun implements Runnable{
private Friend me,date;
public FriendRun(Friend m,Friend d){ me=m;date=d;}
public void run(){ me.sayHA(date); }
}
public static void main(String[] args) {
Friend alice = new Friend("Alice");
Friend bob = new Friend("Bob");
Alice says HA to Bob
Thread t=new Thread(new FriendRun(alice,bob));
Bob says HA to Alice
Thread t1=new Thread(new FriendRun(bob,alice));
t.start();
t1.start();
}}
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
deadlock ‫דוגמא ל‬
public class Friend {
A
private String name;
public Friend(String name){this.name = name;}
B
public String getName(){return this.name;}
public synchronized void sayHA(Friend date) {
t1 FR
A
System.out.format("%s says HA to %s%n",this.name, date.getName());
B
date.sayDA(this);
}
public synchronized void sayDA(Friend date) {
Start()
t2 FR
B
A
System.out.format("%s says DA to %s%n",this.name,date.getName());
}
}
A.sayHA()
‫ נעול‬A
t1: B.sayDA()
‫ נעול‬B ‫א"א‬
‫לא יוצאים מ‬
A.sayHa()
...‫ נשאר נעול‬A
Start()
public class DeadLock {
private static class FriendRun implements Runnable{
B.sayHA()
‫ נעול‬B
private Friend me,date;
public FriendRun(Friend m,Friend d){ me=m;date=d;}
public void run(){ me.sayHA(date); }
t2: A.sayDA()
‫ נעול‬A ‫א"א‬
‫לא יוצאים מ‬
B.sayHa()
...‫ נשאר נעול‬B
}
public static void main(String[] args) {
Friend alice = new Friend("Alice");
Friend bob = new Friend("Bob");
Thread t=new Thread(new FriendRun(alice,bob));
Thread t1=new Thread(new FriendRun(bob,alice));
t.start();
HA ‫אף צד לא סיים לומר‬
t1.start();
}}
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
lock ‫נעילת אובייקטים ע"י‬
import java.util.concurrent.locks.Lock;
public void sayHA(Friend date) {
import java.util.concurrent.locks.ReentrantLock;
if(iCanLockBoth(date)){
public class Friend {
try{
private String name;
System.out.format("%s says HA to %s%n",this.name,date.getName());
date.sayDA(this);
} finally{
private Lock lock = new ReentrantLock();
lock.unlock();
date.lock.unlock();
public Friend(String name){this.name = name;}
}
public String getName(){return this.name;}
} else
public boolean iCanLockBoth(Friend date) {
Boolean myLock = false;
Boolean yourLock = false;
try {
myLock=lock.tryLock();
yourLock=date.lock.tryLock();
} finally {
System.out.format("%s started to say HA but realized %s already
started",name,date.getName());
}
2 ‫ יחסיר אמת רק אם הצלחנו לנעול את‬iCanLockBoth
‫ האובייקטים נעולים ע"י‬2 ‫המנעולים (שלי ושל ה "דייט") כלומר‬
"‫ וכעת אין בעיה שאמירת ה"הא" תצפה ל"דה‬thread ‫אותו ה‬
if (!(myLock&&yourLock)) {
if (myLock) lock.unlock();
if (yourLock) date.lock.unlock();
}
}
return myLock&&yourLock;
}
Alice says HA to Bob
Bob says DA to Alice
Bob started to say HA but realized Alice already started
‫‪ 89-210‬תכנות מתקדם ‪ -‬תרגול ‪6‬‬
‫הממשק ‪Executor‬‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
‫‪Executor‬‬
‫‪ThreadPools‬‬
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
‫• בדוגמאות שראינו עד עתה היה קשר קרוב בין‬
‫המשימה שצריכה להתבצע לבין ה ‪ thread‬שמריץ‬
‫אותה‬
‫• באפליקציות קטנות זה בסדר‪ ,‬אך באפליקציות‬
‫גדולות הגיוני יותר להפריד את יצירת וניהול ה‬
‫‪ threads‬משאר האפליקציה‬
‫• ממשק ה ‪ Executor‬משמש אותנו לכך‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
Executor ‫הממשק‬
:‫• לממשק יש מתודה אחת בשם‬
public void execute(Runnable r(
‫ בידנו‬r.run() ‫• כאשר השליטה איך להריץ את‬
:‫• דוגמאות‬
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
:‫– הרצה ישירה‬
}
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start();
}
}
‫ נפרד‬thread ‫– הרצה ב‬
:‫לכל משימה‬
‫‪ 89-210‬תכנות מתקדם ‪ -‬תרגול ‪6‬‬
‫הממשק ‪Executor‬‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
‫‪Executor‬‬
‫‪ThreadPools‬‬
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
‫• נניח שאנו נרצה לשלוט בכמות ה ‪ threads‬שרצים במקביל‪,‬‬
‫כדי לשלוט בעומס על המערכת‪.‬‬
‫• נוכל לממש תור שיאפשר רק ל ‪ N‬מסוים של ‪ threads‬לרוץ‬
‫מתוכו‪ .‬שיטה זו נקראת ‪ThreadPool‬‬
‫• אופן המימוש‪:‬‬
‫– במתודה ‪ execute‬פשוט נכניס את ‪ r‬לתור‪.‬‬
‫– נממש מתודה בשם ‪ run‬ששולפת ‪ Runnables N‬מהתור‪ ,‬ומריצה‬
‫אותם ב ‪ threads‬משלהם‬
‫– לא נשלוף אחרים כל עוד אלו לא הסתיימו‬
‫• אבל נצטרך לטפל במקרים שונים של ‪ wait ,sleep‬וכו' שזה‬
‫כבר יותר קשה לממש בצורה טובה‬
‫• לכן ב ‪ java.util.concurrent‬כבר ממשו ‪ThreadPools‬‬
‫חזקים וגמישים‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
ThreadPools
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
public static void main(String[] args) {
import java.util.concurrent.Executors;
Executor executor = Executors.newSingleThreadExecutor();
public class ThreadTest3 {
executor.execute (new RunnableTask1 ());
executor.execute (new RunnableTask2 ());
private static void delay(long ms){
try { Thread.sleep(ms);}
executor.execute (new RunnableTask3 ());
catch (InterruptedException e) {}
((ExecutorService) executor).shutdown();
}
}
private static class RunnableTask1 implements Runnable{
public void run(){
System.out.println("task1 started");
delay(10000);
System.out.println("task1 finished");
}
}…
RunnableTask2 ‫ובהתאמה המחלקות‬
RunnableTask 3 ‫ו‬
‫ שיוצר‬factory ‫אנו קוראים בצורה סטטית ל‬
‫ כאשר במקרה שלנו‬,ExectuterService
‫ מאפשר רק‬newSingleTreadExecutor()
.‫ אחד לרוץ בכל פעם‬thread ‫ל‬
?‫איך יראה הפלט‬
task1 started
task1 finished
task2 started
task2 finished
task3 started
task3 finished
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
ThreadPools
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
public static void main(String[] args) {
import java.util.concurrent.Executors;
Executor executor = Executors.newFixedThreadPool (2);
public class ThreadTest3 {
executor.execute (new RunnableTask1 ());
executor.execute (new RunnableTask2 ());
private static void delay(long ms){
try { Thread.sleep(ms);}
executor.execute (new RunnableTask3 ());
catch (InterruptedException e) {}
((ExecutorService) executor).shutdown();
}
}
private static class RunnableTask1 implements Runnable{
public void run(){
System.out.println("task1 started");
delay(10000);
System.out.println("task1 finished");
}
}…
RunnableTask2 ‫ובהתאמה המחלקות‬
RunnableTask 3 ‫ו‬
Executors.newFixedThreadPool ‫הפעם‬
.‫ לרוץ‬threads ‫מאפשר רק למספר מסוים של‬
?‫איך יראה הפלט‬
task1 started
task2 started
task1 finished
task2 finished
task3 started
task3 finished
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
ThreadPools
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
public static void main(String[] args) {
import java.util.concurrent.Executors;
Executor executor = Executors.newCachedThreadPool();
public class ThreadTest3 {
executor.execute (new RunnableTask1 ());
executor.execute (new RunnableTask2 ());
private static void delay(long ms){
try { Thread.sleep(ms);}
executor.execute (new RunnableTask3 ());
catch (InterruptedException e) {}
((ExecutorService) executor).shutdown();
}
}
private static class RunnableTask1 implements Runnable{
public void run(){
System.out.println("task1 started");
delay(10000);
System.out.println("task1 finished");
}
}…
RunnableTask2 ‫ובהתאמה המחלקות‬
RunnableTask 3 ‫ו‬
Executors.newCachedThreadPool ‫ל‬
threads ‫אין הגבלה על מספר ה‬
?‫איך יראה הפלט‬
task1 started
task2 started
task3 started
task1 finished
task3 finished
task2 finished
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
Callable, Future
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
public static void main(String[] args) throws
InterruptedException, ExecutionException {
import java.util.concurrent.ExecutorService;
ExecutorService executor = Executors.newCachedThreadPool();
import java.util.concurrent.Executors;
Future<Integer> futures[]=new Future[3];
import java.util.concurrent.Future;
for(int i=0;i<3;i++)
futures[i]=executor.submit (new CallableTask(i+1));
public class ThreadTest3 {
executor.shutdown();
private static void delay(long ms){
for(int i=0;i<3;i++)
try { Thread.sleep(ms);}
System.out.printf("task%d finished\n",futures[i].get());
catch (InterruptedException e) {}
}
}
private static class CallableTask implements Callable<Integer>{
Integer i;
public CallableTask(int i){
this.i=new Integer(i);
}
public Integer call() throws Exception {
}
task2 started
System.out.printf("task%d started\n",i);
task3 started
delay(10000);
task1 finished
return i;
}
task1 started
task3 finished
task2 finished
‫ יודע לעבוד גם עם‬ExecutorService
‫ גם לו‬Runnable ‫ שבדומה ל‬,Callable
‫ אך היא יכולה להחזיר‬,call ‫מתודה אחת‬
‫ וכך‬,‫ כרצוננו‬exception ‫ערך ואף לזרוק‬
.‫קל יותר להעביר מידע‬
‫ תחזיר את הערך של‬submit ‫המתודה‬
.Future ‫ לתוך אובייקט מסוג‬call
.‫ מתודות שימושיות נוספות‬Future ‫ל‬
‫‪ 89-210‬תכנות מתקדם ‪ -‬תרגול ‪6‬‬
‫מבני נתונים מסונכרנים‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
‫‪Executor‬‬
‫‪ThreadPools‬‬
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
‫רוב מבני הנתונים של ‪ java.util‬אינם מסונכרנים‬
‫ניתן לעטוף אותם בטיפוסים מסונכרנים לדוגמא‪:‬‬
‫= ‪private Map<String,Integer> hm‬‬
‫כך רק מי שצריך‪ ,‬משלם את‬
‫‪Collections.synchronizedMap( new‬‬
‫מחיר זמן הריצה‪...‬‬
‫;))(>‪HashMap<String,Integer‬‬
‫בעוד שפעולות בודדות הן ‪ ,thread-safe‬רצף של פעולות התלויות‬
‫כל אחת בתוצאת קודמתה‪ ,‬אינה ‪thread-safe‬‬
‫טעות נפוצה היא לחשוב ששיטה זו ‪ thread-safe‬לגמריי‬
‫בגרסא ‪ ,5‬נוספו מבני הנתונים ב ‪java.util.concurrent‬‬
‫מבני נתונים אלו הם ‪ thread-safe‬לחלוטין‪ ,‬ואף מהירים בהרבה‬
‫ממבנה רגיל העטוף ב ‪synchronized‬‬
‫מבני נתונים‪:‬‬
‫– >‪ArrayBlockingQueue<E‬‬
‫– >‪ConcurrentHashMap<K,V‬‬
‫– >‪ConcurrentLinkedQueue<E‬‬
‫‪ 89-210‬תכנות מתקדם ‪ -‬תרגול ‪6‬‬
‫הטמעה‬
‫•‬
‫•‬
‫•‬
‫•‬
‫•‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
‫‪Executor‬‬
‫‪ThreadPools‬‬
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
‫האם תמיד מובטח שהמחשב ימליץ ל ‪ Bob‬לצאת‬
‫עם ‪( ?Alice‬הקוד בשקף הבא)‬
‫הראו תוכנית שתבטיח זאת‬
‫כתבו תוכנית שמעדכנת ‪ HashMap‬בכמה‬
‫‪ threads‬ברמה שחוסר הסנכרון יפגע בתוצאות‬
‫עטפו את המחלקה בסנכרון‪ ,‬ומדדו את הזמן‪.‬‬
‫החליפו את מבנה הנתונים ל‬
‫‪ ConcurrentHashMap‬ומדדו את הזמן שוב‬
‫הקדמה‬
‫תזמון משימות‬
‫משתנים אטומיים‬
‫מנעולים‬
Executor
ThreadPools
‫מבני נתונים מסונכרנים‬
‫הטמעה‬
6 ‫ תרגול‬- ‫ תכנות מתקדם‬89-210
public class ThreadTest4 {
static String message;
private static class CorrectorThread extends Thread {
public void run() {
try {sleep(1000);}
catch (InterruptedException e) {}
message = "Bob, ask Alice on a date.";
}
}
public static void main(String args[]) throws InterruptedException {
(new CorrectorThread()).start();
message = "Bob, don't ask Alice on a date.";
Thread.sleep(2000);
System.out.println(message);
}
}