Wykład 9: Programowanie Wielo

Transkrypt

Wykład 9: Programowanie Wielo
Wykład 9:
Programowanie Wielo-Wątkowe
Programowanie Równoległe
oparte na procesach:
●
wykonywalny program
●
własna przestrzeń adresowa
●
droga komunikacja i zmiana kontekstu
●
oparte na wątkach:
●
wątek to część programu
●
wspólna przestrzeń adresowa
●
tania komunikacja i zmiana kontekstu
●
Programowanie Równoległe w Javie
Oparte o wątki:
stany wątku: wykonywany, gotowy, zawieszony,
wznowiony, zablokowany
●
priorytety: wątek o wyższym priorytecie zawiesza ten
o niższym
●
synchronizacja: tylko jeden wątek wykonuje metodę
synchroniczną na danym obiekcie
●
komunikacja: przez metody synchroniczne
●
Wątek Główny
tworzony automatycznie
●
wątek z którego powstają inne wątki
●
pierwszy powstaje, ostatni kończy się
●
Uzyskanie odwołania do bieżącego wątku:
static Thread currentThread()
Wątek Główny: Przykład
class CurrentThreadDemo {
public static void main(String args[]) {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t);
t.setName("My Thread");
System.out.println("After name change: " + t);
}
}
try {
for(int n = 5; n > 0; n--) {
System.out.println(n);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main interrupted");
}
Klasa Thread
Metody klasy Thread:
●
getName – uzyskaj nazwę wątka
●
getPriority – uzyskaj priorytet wątka
●
isAlive – czy wątek działa?
●
join – czekaj na zakończenie wątka
●
run – wykonanie wątka
●
sleep – zawieś wątek na jakiś czas
●
start – wystartuj wątek
Tworzenie Nowego Wątka
przez implementację interfejsu Runnable
●
przez dziedziczenie po klasie Thread
●
Kiedy który?
wśród metod Thread, tylko run() musi być
przesłonięty
●
wybierz dziedziczenie po Thread, gdy inne metody
muszą być przesłonięte
●
Tworzenie Nowego Wątka: Runnable
class NewThread implements Runnable {
Thread t;
NewThread() {
t = new Thread(this, "Demo Thread");
System.out.println("Child thread: " + t);
t.start(); // Start the thread
}
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
Tworzenie Nowego Wątka: Runnable
}
System.out.println("Exiting child thread.");
}
class ThreadDemo {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Tworzenie Nowego Wątka: Thread
class NewThread extends Thread {
NewThread() {
super("Demo Thread");
System.out.println("Child thread: " + this);
start(); // Start the thread
}
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println("Child Thread: " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
Tworzenie Nowego Wątka: Thread
}
System.out.println("Exiting child thread.");
}
class ExtendThread {
public static void main(String args[]) {
new NewThread(); // create a new thread
try {
for(int i = 5; i > 0; i--) {
System.out.println("Main Thread: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Main interrupted.");
}
System.out.println("Main thread exiting.");
}
}
Wiele Wątków: Przykład 1
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
Wiele Wątków: Przykład 2
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println(name + "Interrupted");
}
System.out.println(name + " exiting.");
}
Wiele Wątków: Przykład 3
class MultiThreadDemo {
public static void main(String args[]) {
new NewThread("One"); // start threads
new NewThread("Two");
new NewThread("Three");
try {
// wait for other threads to end
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main Interrupted");
}
}
}
System.out.println("Main thread exiting.");
Zakończenie Wątku
Metoda zwraca true, jeśli wątek na której jest
wywołana wykonuje się:
final boolean isAlive()
Metoda czeka aż wątek na której wykonuje się
zakończy się:
final void join() throws InterruptedException
Zakończenie Wątku: Przykład 1
class NewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
Zakończenie Wątku: Przykład 2
}
// This is the entry point for thread.
public void run() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
Zakończenie Wątku: Przykład 3
class DemoJoin {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println(ob1.t.isAlive());
System.out.println(ob2.t.isAlive());
System.out.println(ob3.t.isAlive());
// wait for threads to finish
try {
System.out.println("Waiting to finish.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) {
System.out.println("Main Interrupted");
}
Zakończenie Wątku: Przykład 3
System.out.println(ob1.t.isAlive());
System.out.println(ob2.t.isAlive());
System.out.println(ob3.t.isAlive());
}
}
System.out.println("Main thread exiting.");
Priorytet Wątku
Decyduje kiedy wątek może się wykonywać.
W praktyce, czas CPU poświęcony dla wątku zależy od
szeregu innych czynników.
Ustalenie i sprawdzenie priorytetu:
final
final
final
final
final
void setPriority(int level)
int getPriority()
int MIN_PRIORITY = 1
int MAX_PRIORITY = 10
int NORM_PRIORITY = 5
Priorytet Wątku: Przykład 1
class clicker implements Runnable {
int click = 0;
Thread t;
Zapewnia że running jest sprawdzane w każdej
iteracji pętli, inaczej pętla może być optymalizowana.
private volatile boolean running = true;
Priorytet Wątku: Przykład 2
public clicker(int p) {
t = new Thread(this);
t.setPriority(p);
}
public void run() {
while (running) { click++; }
}
public void stop() { running = false; }
}
public void start() { t.start(); }
Priorytet Wątku: Przykład 3
class HiLoPri {
public static void main(String args[]) {
Thread.currentThread().
setPriority(Thread.MAX_PRIORITY);
clicker hi = new
clicker(Thread.NORM_PRIORITY+2);
clicker lo = new
clicker(Thread.NORM_PRIORITY – 2);
lo.start();
hi.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("Main interrupted.");
}
Priorytet Wątku: Przykład 4
lo.stop();
hi.stop();
// Wait for child threads to terminate.
try {
hi.t.join();
lo.t.join();
} catch (InterruptedException e) {
System.out.println(
"InterruptedException caught");
}
}
}
System.out.println("Low: " + lo.click);
System.out.println("High: " + hi.click);
Synchronizacja Wątków
Kiedy kilka wątków korzysta z dzielonych zasobów.
Jak zapewnić aby tylko jeden wątek używał ten zasób.
Monitor: obiekt do którego może wejść jeden wątek.
Dwie metody:
użycie metod synchronized
●
użycie instrukcji synchronized
●
Metody Synchronized
Każdy obiekt ma związany z nim monitor.
Aby wejść do monitora, wywołaj jedną z metod
oznaczonych jako synchronized.
W tym czasie, wszystkie wątki muszą czekać aby
wykonać metodę synchronized na tym obiekcie.
Aby wyjść z monitora, wątek musi wyjść z metody
synchronized.
Metody Synchronized: Przykład 1
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
Metody Synchronized: Przykład 2
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
}
public void run() {
target.call(msg);
}
Metody Synchronized: Przykład 3
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synch");
Caller ob3 = new Caller(target, "World");
}
}
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
Metody Synchronized
Trzy wywołania metody call przeplatają się w czasie.
Należy zapewnić serializację wykonania call:
class CallMe {
synchronized void call(Sting msg) {
...
}
}
To zapobiegnie aby inne wątki wykonywały metodę
call w czasie gdy inny wątek ją wykonuje.
Instrukcja Synchronized
Synchronizacja dostępu do klasy która nie była
zaprojektowana dla wielo-wątkowości.
synchronized(object) {
...
}
Zapewnia że wywołanie metody składowej obiektu
wykona się tylko po wejściu do monitora tego obiektu.
Instrukcja Synchronized: Przykład 1
class Callme {
void call(String msg) {
System.out.print("[" + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
System.out.println("]");
}
}
Instrukcja Synchronized: Przykład 2
class Caller implements Runnable {
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
public void run() {
synchronized(target) {
target.call(msg);
}
}
}
Instrukcja Synchronized: Przykład 3
class Synch1 {
public static void main(String args[]) {
Callme target = new Callme();
Caller ob1 = new Caller(target, "Hello");
Caller ob2 = new Caller(target, "Synch");
Caller ob3 = new Caller(target, "World");
}
}
// wait for threads to end
try {
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch(InterruptedException e) {
System.out.println("Interrupted");
}
Instrukcja Synchronized: Przykład 3
String msg;
Callme target;
Thread t;
public Caller(Callme targ, String s) {
target = targ;
msg = s;
t = new Thread(this);
t.start();
}
// synchronize calls to call()
public void run() {
synchronized(target) { // synchronized block
target.call(msg);
}

Podobne dokumenty