41
Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Embed Size (px)

Citation preview

Page 1: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Java Thread Scheduling Example

Lin,Yong

Thread PoolsRound-Robin scheduling

Job Scheduling

Page 2: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Thread Pool

Wieso brauchen wir ThreadPool? Wenn es viele Threads gibt, die können nicht gleichzeitig behandelt werden , dann brauchen wir den Threadpool Scheduler.

Um die Konkurrenz der CPUresource zu vermeiden. Um das Programm effizienter zu machen.

Page 3: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

ThreadPoolThread Objekte ( ThreadPoolRequest )

ThreadPool

Page 4: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

ThreadPoolThread Objekte (ThreadPoolRequest)

ThreadPool

Page 5: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Wie funktioniert das ThreadPool ? ThreadPool verfügt über einige runnable Objekte (ThreadPoolRequest). ThreadPool gibt dem ThreadPoolThread die Objekte als Referenz ab Durch Verwaltung von ThreadPoolThread können wir die runnable Objekte (request) kontrollieren. Wegen der Bestimmung der Anzahl von ThreadPoolThread

können maximal die gleich vielen Objekte gleichzeitig laufen.

Page 6: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

import java.util.*;

public class ThreadPool {

class ThreadPoolRequest {Runnable target ;ThreadPoolRequest (Runnable t) {} // Constructor

}

class ThreadPoolThread extends Thread {ThreadPool parent;boolean shouldRun = true;

ThreadPoolThread( ThreadPool parent, int i) {} //Constructor

Page 7: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public void run() {ThreadPoolRequest obj = null;while ( shouldRun ) {

try {while (obj == null && shouldRun) {

try {obj = (ThreadPoolRequest)

parent.objects.elementAt(0); parent.objects.removeElementAt(0);

} catch (Exception e) {}if ( obj == null ) {

parent.cvAvailable.cvWait(); } // Pool has to wait to be filled with new threads again

if (!shouldRun ) return ;obj.target.run();nObjects--;

if ( nObjects == 0 ) { parent.cvEmpty.cvSignal();}}

Page 8: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Vector objects ;int nObjects = 0;

BusyFlag cvFlag;CondVar cvAvailable, cvEmpty ;ThreadPoolThread poolThreads[];

public ThreadPool (int n) {cvFlag = new BusyFlag();cvAvailable = new CondVar(cvFlag);objects = new Vector();poolThreads = new ThreadPoolThread[n];for (int i = 0;i < n; i++) {poolThreads[i] = new ThreadPoolThread(this, i);

poolThreads[i].start();}

}

Page 9: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

private void add(Runnable target) {try {

cvFlag.getBusyFlag();objects.addElement ( new

ThreadPoolRequest(target));nObjects++;cvAvailable.cvSignal();

} finally {cvFlag.freeBusyFlag();

}}

Page 10: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Round-Robin scheduling

Auf JVM mit „Native-Thread“ Implementierung steht Round-Robin Schedulingautomatisch schon.

Wenn wir auf JVM mit „Green-Thread“ Implementierung haben wollen ,dann brauchen wir Round-robin scheduling.

Wo und wann brauchen wir Round-Robin scheduling?--- auf „Green-Thread“ Implementierung von Java virtual machine--- Wenn es mehr als 1 CPU-intensiver Thread gibt.

Fundamentales Prinzip--- Jedem Thread wird eine bestimmte Zeit gegeben, wo es laufen kann.

Page 11: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Ein einfacher Round-Robin Scheduler

---Es ist nur ein Thread mit höherer Priorität, der periodisch aufwacht und sofort wieder blockiert.

---Anm: Der SimpleScheduler funktioniert nur unter JVM mit native-thread Implementierung. d.h. JVM unterstützt eigentlich schon Round-robin scheduling.

Page 12: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class SimpleScheduler extends Thread {int timeslice;

public SimpleScheduler(int t) {timeslice = t;setPriority(Thread.MAX_PRIORITY);setDaemon(true);

}

public void run() {while ( true ) {

try {sleep(timeslice);

} catch(Exception e ){}}

}}

Page 13: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

class TestThread extends Thread {String id;

public TestThread(String s) {id = s;}

public void doCalc(int i) {...}

public void run() {int i;for ( i = 0; i < 10; i++ ) {

doCalc(9);System.out.println(id);

...}

Page 14: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class Test {public static void main( String args[] ) {

new SimpleScheduler(100).start();TestThread t1, t2, t3;t1 = new TestThread("Thread 1");t1.start();t2 = new TestThread("Thread 2");t2.start();t3 = new TestThread("Thread 3");t3.start();

}}

Page 15: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Thread 1Thread 1Thread 2Thread 2Thread 3 Thread 3Thread 1Thread 1......

Das Ergebnis :

Page 16: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Drei Phasen

1) PRIORITY 5 : t2 t3 t1 NULL BLOCKED : SimpleScheduler NULL

2) PRIORITY 5 : t2 t3 t1 NULL PRIORITY 10: SimpleScheduler NULL

3) PRIORITY 5 : t3 t1 t2 NULL BLOCKED : SimpleScheduler NULL

Page 17: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Ein vollständigerer Scheduler : CPUScheduler

Der Scheduler funktioniert unter beiden Round-robin-unterstützten undnicht-Round-robin-unterstützten JVM.Hier bestimmt der CPUScheduler selbst die Ausführung von Threads.

Wie funktioniert der CPUScheduler ?--- Wir bauen diesen Scheduler , indem wir die Prioritäten in drei Stufen setzen. Stufe 6 Der Scheduler selbst ist ein separater Thread mit Priorität 6. Meistens ist er in inaktiv (blockiert). Stufe 4 Der Scheduler wählt einen Thread aus und weist diesem Thread mit Priorität 4 zu. Er ist mit höchsten Priorität aktiv ( unblockert ). Stufe 2 Alle restlichen Threads unter Kontrolle von unserem Scheduler laufen mit Priorität 2. Sie warten bis sie ausgewählt werden.

Page 18: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class CPUScheduler extends Thread {private int timeslice; // # of milliseconds thread

// should runprivate CircularList threads; // All the threads we're

// scheduling

public boolean shouldRun = false ; // Exit when this is set

public CPUScheduler(int t) {threads = new CircularList();timeslice = t;

}

public void addThread(Thread t) {threads.insert(t);t.setPriority(2);

}

Page 19: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public void removeThread(Thread t) {t.setPriority(5);threads.delete(t);

}

public void run(){Thread current;setPriority(6);while (shouldRun) {

current = ( Thread ) threads.getNext();if (current == null)

return;current.setPriority(4);try {

Thread.sleep(timeslice);} catch(InterruptedException ie) {};current.setPriority(2);

... }

Page 20: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

class TestThread extends Thread {String id;public TestThread(String s) {

id = s;}

public void doCalc(int i) {}

public void run() {int i;for ( i = 0; i < 10; i++ ) {

doCalc(9);System.out.println(id);

}}

}

Page 21: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class Test {public static void main( String args[] ) {

CPUScheduler c = new CPUScheduler(100);TestThread t1, t2, t3;t1 = new TestThread("Thread 1");t2 = new TestThread("Thread 2");t3 = new TestThread("Thread 3");c.addThread(t1);c.addThread(t2);c.addThread(t3);t1.start();t2.start();t3.start();c.start();

}}

Page 22: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Nachdem c.start() Methode aufgerufen wird.

PRIORITY 2 : t1 t2 t3 NULLPRIORITY 6 : CPUScheduler NULL

Wenn der CPUScheduler Thread fängt mit Run() Methode an ,ändert sich die Priorität von Thread t1 zu 4:

PRIORITY 2 : t2 t3 NULLPRIORITY 4 : t1NULLPRIORITY 6 : CPUScheduler NULL

Bemerkung: Es gibt immer nur einen Thread mit Priority 4. Das kann kein Round-Robin Scheduling garantieren.

Page 23: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Wenn der CPUScheduler blockiert, wird t1 aktueller laufender Thread:

PRIORITY 2 : t2 t3 NULLPRIORITY 4 : t1 NULLBLOCKED : CPUScheduler NULL

Wenn der CPUScheduler aufwacht, ändert er die Prioritätdes t1 zurück zu 2 , des t2 zu 4

PRIORITY 2 : t3 t1 NULLPRIORITY 4 : t2 NULLPRIORITY 6 : CPUScheduler NULL

Page 24: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Einige Verbesserungen

Einstellung 1 : Synchronisieren Daten innerhalb des CPUSchedulers.

Cause : Unzulässiger Zugriff von setPriority(). (Wenn die Methode removeThread() aufgerufen wird und er ist genau der Thread , den der CPUScheduler als aktueller laufender Thread markieren will.)Solution : Ändern die Variable current zu einer Instanz Variable, so dass beide run() und removeThread() Methoden erreichen können. ( synchronize access ) , wenn der Thread schon gelöscht worden ist, dann soll ihm die Priorität nicht mehr nochmal zugewiesen werden.

Page 25: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class CPUScheduler extends Thread {...private Thread current;

public void removeThread(t) {t.setPriority(5);threads.delete(t);synchronized(this) {

if (current == t )current = null;

... }public void run() {...try {

Thread.sleep(timeslice);} catch(InterruptedException ie) {

synchronized(this) { // um den selben Wert zu testenif (current != null )current.setPriority(2);

... }

Page 26: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Einstellung 2 : Sicherung des CPUScheduler Threads

Cause : Der current Thread terminiert, ohne dass die Referenz im Scheduler gelöscht wird.

Der Thread, dem wir schon Priorität 4 zugewiesen haben ,endet seine Run() Methode wenn unser CPUScheduler blockiert.

Oder ein Thread mit Priorität 4 ruft die stop()-Methode einen Threadmit Priorität 2 auf. Unser CPUScheduler wählt diesen nochirgendwann als nächsten Thread aus und setzt seine Priorität.

Solution : Alle Aufrufe von setPriority() werden in einem try/catch-Block ausgeführt, um solche unerwartete Sache zu behandeln.

** Die abhängige codes sind weggenommen.

Page 27: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Einstellung 3 : Mehr Sicherungsmodifikation

Cause : Wenn zwei Threads es versuchen , eine CPUScheduler Klasse zu erzeugen. Sie könnten konkurrieren, die Threads zu regeln.

Solution : Wir erzeugen eine statische Variable in der Klasse, und prüft ,ob eine Instanz von CPUScheduler Klasse schon existiert hat.

Page 28: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class CPUScheduler extends Thread {private static boolean initialized = false;private synchronized static boolean isInitialized() {

if (initialized)return true;

initialized = true ;return false;

}

public CPUScheduler(int t) {if(isInitialized()) throw SecurityException("Already

initialized");threads = new CircularList();timeslice = t;}

}

Page 29: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Einstellung 4 : Entwurf eines Austrittmechanismus

Wir setzen CPUScheduler zu einem DaemonThread. Also wenn eskeine weitere Threads zu regeln gibt, endet sich der CPUSchedulerAutomatisch.

Einstellung 5 : Non-CPU-intensive threads

Wenn der aktuelle laufende Thread blockiert, dann kann solches passieren.

Wenn der CPUscheduler nach einiger Zeit wieder dem blockierten ThreadPriorität 4 zuweist, bleibt der Thread noch in blockierter Situation. EinThread aus Priorität 2 wird unerwartet der akutelle laufende Thread.

Page 30: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Job Scheduling

Was ist ein Job-Scheduling?--- JobScheduling ist abhängig von Kontrolle der Zeit, wo die Objekte ausgeführt werden. Nämlich in einer bestimmeten Zeit wird eine bestimmte Aufgabe ausgeführt wird.

Wo brauchen wir JobScheduling?z.B. Ein Wortprozessor speichert das Zwischenergebnis jeder 5 Minuten , um die Verlust von Daten zu vermeiden. In einem Animate Applet sollen wir jede Sekunde repaint() Methode aufrufen.

Page 31: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Welche Attributen hat JobNode ?

Runnable job ; Date executeAt; // wann ausgeführt zu werden Long interval; // Mehrmaligkeit Int count;

Wie startet der Jobscheduler Jobs?

--- Entweder wir fügen das runnable Objekt in einen Threadpool ein.

--- Oder starten wir einen neuen Thread, der den Job ausführen kann.

Page 32: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Anmerkung :1) Der Scheduler kann auch rechnen , wieviele Male soll ein

Job noch ausgeführt werden.

2) Nach jeder Ausführung einer Arbeit soll der Scheduler dafür entscheiden, ob es noch weitere Jobs gibt , die ausgeführt werden sollen und wann sollen die Jobs ausgeführt werden.

3) Ob ein Job beendet wird , ist durch die Methode updateJobNode() zu entscheiden.

4) Einfügen und Löschen der Jobs sind durch die MethodenaddJob() und deleteJob() zu implementieren.

Page 33: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

import java.util.*;

public class JobScheduler implements Runnable {final public static int ONCE = 1;final public static int FOREVER = -1;final public static long HOURLY = (long)60*60*1000;final public static long DAILY = 24*HOURLY;final public static long WEEKLY = 7*DAILY;final public static long MONTHLY = -1;final public static long YEARLY = -2;

private class JobNode {public Runnable job ;public Date executeAt;public long interval ;public int count;

}

Page 34: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

private ThreadPool tp;private DaemonLock dlock = new DaemonLock();private Vector jobs = new Vector(100);

public JobScheduler(int poolSize) {tp = (poolSize > 0) ? new ThreadPool(poolSize) : null ;Thread js = new Thread(this);js.setDaemon(true);js.start();

}

private synchronized void addJob(JobNode job) {dlock.acquire();jobs.addElement(job);notify();

}

Page 35: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

private synchronized void deleteJob(Runnable job) {for (int i = 0; i < jobs.size(); i++ ) {

if (((JobNode) jobs.elementAt(i)).job == job) {jobs.removeElementAt(i);dlock.release();break;

}}

}

Page 36: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

private JobNode updateJobNode(JobNode jn) {Calendar cal = Calendar.getInstance();cal.setTime(jn.executeAt);if(jn.interval == MONTHLY) {

cal.add(Calendar.MONTH, 1);jn.executeAt = cal.getTime();

}else if (jn.interval == YEARLY) {cal.add(Calendar.YEAR, 1);jn.executeAt = cal.getTime();

}else {jn.executeAt = new Date (

jn.executeAt.getTime() + jn.interval);}jn.count =

(jn.count == FOREVER )? FOREVER : jn.count -1;

return (jn.count != 0 ) ? jn : null ;}

Page 37: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

private synchronized long runJobs() {long minDiff = Long.MAX_VALUE;long now = System.currentTimeMillis();for ( int i = 0; i < jobs.size();) {

JobNode jn = (JobNode) jobs.elementAt(i);if (jn.executeAt.getTime()<= now) {

if (tp !=null) {tp.addRequest(jn.job);}else { Thread jt = new Thread(jn.job);

jt.setDaemon(false);jt.start(); }

if (updateJobNode(jn) == null) {jobs.removeElementAt(i);dlock.release();}

}else { long diff = jn.executeAt.getTime() - now;minDiff = Math.min(diff,minDiff);i++;}}

return minDiff;}

Page 38: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public synchronized void run() {while (true) {

long waitTime = runJobs();try {

wait(waitTime);} catch (Exception e) {};

} }

public void cancel(Runnable job) { deleteJob(job); }}

Page 39: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

public class DaemonLock { private int lockCount = 0; public synchronized void acquire() { if (lockCount++ = 0 ) {

Thread t = new Thread(this);t.setDaemon(false);t.start();}

} public synchronized void release() {

if (--lockCount == 0) {notify();}

} public synchronized void run() {

while (lockCount != 0) {try {

wait();}catch(InterruptedException ex) {};

}}}

Page 40: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Wieso brauchen wir DaemonLock ?

Mit DaemonLock können wir den JobScheduler zu einem DaemonThreadmachen . Wenn es keine Jobs mehr zu verwalten gibt, endet sich derJobScheduler. Dies läßt sich durch Zuweisung und Entfernung vonDaemonLock beim Einfügen und Löschen von Jobs realisieren.

Aber warum setzen wir den JobScheduler nicht einfach zu einemDaemonThread ?Wenn es noch Threads gibt, die schon durch unseren JobSchedulerverwaltet sind , aber trotzdem noch nicht ausgeführt werden.Kann sein , dass sich unser JobScheduler als DaemonThread endet ,während einige Threads noch warten, ausgeführt zu werden. Und nachdieser Ausführung fehlt diesen Threads ein SchedulerThread.

Page 41: Java Thread Scheduling Example Lin,Yong Thread Pools Round-Robin scheduling Job Scheduling

Zusammenfassung

ThreadPool Wenn es mehr als sinvoll ausführbare Threads gibt. Roundrobin Scheduling SimpleScheduler --- Nur unter Native Thread JVM CPUScheduler --- Unter beiden Native-Thread und Green-Thread JVM (selbst kontrollieren) Job Scheduling Die Jobs werden zum angegebenen Zeitpunkt gestartet.