6.3 ereignisbasierte systeme ereignis (event) : eine ereignis-quelle (event source, publisher)...
Post on 05-Apr-2015
113 Views
Preview:
TRANSCRIPT
6.3 Ereignisbasierte Systeme
Ereignis (event) :
eine Ereignis-Quelle (event source, publisher) generiert
Benachrichtigung (event notification), an der i.a. mehrere
Ereignis-Senken (event sinks, subscribers) interessiert sind.
Z.B. „Pixelpark-Aktie fällt unter 1,2!“„Druck steigt über 4,5!“
Für die Quelle ist es irrelevant, wer auf ein Ereignis wie reagiert.
Die Senken sind an ganz bestimmten Ereignissen interessiert.
Verschiedenartige Ereignisse werden durch
verschiedene Ereigniskanäle (event channels) repräsentiert,
die auch gemäß den Ereignisnachrichten getypt sein können
Verschiedenartige Ereignisse werden durch
verschiedene Ereigniskanäle (event channels) repräsentiert,
die auch gemäß den Ereignisnachrichten getypt sein können
Quelle Senken
nachrichtenbasierter Ereigniskanal (hier im Beispiel mit 3 Senken)
Aufrufbasierte Variante: asynchroner Prozeduraufruf!
Senke für Ereignis(se) kann gleichzeitig
Quelle anderer Ereignis(se) sein.
Ereignisbasiertes System (event-based system) =
Prozeßnetz aus Ereignisquellen und -senken
Prozeß erklärt sich dynamisch zur Senke für einen
Ereigniskanal – „abonniert das Ereignis“ (subscription)
und kann das Abonnement später wieder „kündigen“
(cancellation).
6.3.1 Ereignisorientierte Programmierung
Typischer aufrufbasierter Ereigniskanal:
interface Event<Notification> {void signal(Notification n);
// forks all subscribers, passing n void subscribe(Handler<Notification> h);
// subscribes event handler hvoid cancel(Handler<Notification> h);
// cancels subscription}
interface Handler<Notification> {void handle(Notification n);
// handles n }
Ereignisquelle für ein Ereignis lowPressure :...lowPressure.signal(pressure);...
Behandlung des Ereignisses:...Handler h = new Handler<Float>(){
void handle(Float press){ ..hier.. }};...lowPressure.subscribe(h);......lowPressure.cancel(h);...
6.3.2 Das Beobachter-Muster(observer pattern)
ist ein objektorientiertes Entwurfsmuster (design pattern),
das als sequentielle Variante der ereignisbasierten
Interaktion betrachtet werden kann:
Subjectattach(Observer)detach(Observer)notify()
Observer
update()
ConcreteSubject
ConcreteObserver
update()
*
s:ConcreteSubject x:ConcreteObserver y:ConcreteObserver
s.attach(this);
s:ConcreteSubject x:ConcreteObserver y:ConcreteObserver
s.attach(this);
s.attach(this);
s:ConcreteSubject x:ConcreteObserver y:ConcreteObserver
s.attach(this);
s.attach(this);
notify(); o[1].update(); o[2].update();
s:ConcreteSubject x:ConcreteObserver y:ConcreteObserver
s.attach(this);
s.attach(this);
notify(); o[1].update(); o[2].update();
notify(); o[1].update(); o[2].update();
Analogie: Ereigniskanal: event.subscribe(handler)
Beobachter-Muster: subject.attach(observer)
Unterstützung durch java.util:
interface Observer {void update(Observable o, Object notification);}
class Observable {public synchronized void addObserver(Observer o);public synchronized void delObserver(Observer o);public void notifyObservers(Object notification);.....}
6.3.3 Das Ereignis-Modell von Java
orientiert sich am Beobachter-Muster:
event listener = Beobachter (= Ereignissenke)
event source = Beobachteter (= Ereignisquelle)
event type + event source (= Ereigniskanal/typ)
(event type in AWT per Namenskonvention)
event object = Benachrichtigung
(für GUI-Ereignisse: Paket java.awt.event u.a.)
Abonnieren eines Ereignisses: event type X + event source
Ereigniskanal: event.subscribe(handler);
Beobachter-Muster: subject.attach(observer);
Java AWT: source.addXListener(anXListener);
z.B.
button.addActionListener( new ActionListener(){
public void actionPerformed (ActionEvent e){ Button b = e.getSource(); ...} } );
Ereignisquelle ist hier ein Button-Objekt: das Ereignis wird durchKlicken auf die entsprechende Taste der GUI ausgelöst.
6.4 Verteilte Algorithmen
bewerkstelligen Problemlösung durch Kooperationkommunizierender Prozesse:
alle Beteiligten kennen ihre Partner (peers)und deren Funktionsweise;
Partner sind häufig gleichberechtigt,haben auch oft identischen Code,
verwenden meist direkte Interprozeßkommunikation(ohne explizite Kanäle).
Problem:
Sichere Nachrichtenübertragung von A nach Bunter Verwendung zweier unsicherer Kanäle,
Sender A Empfänger B
auf denen sporadisch Nachrichten verlorengehen.
6.4.1 Das Alternating-Bit-Protokoll
Lösungsidee: Nachrichten quittieren – neue Nachricht erst dann schicken, wenn Quittung eingetroffen; evtl. letzte Nachricht wiederholen.
Sender Empfänger
Nachricht
Quittung
Sender Empfänger
Nachricht
Quittung
Nachricht
Quittung
(timeout)
? Ist letzte Nachrichtangekommen, oder muß sie wiederholt werden ?
Nachrichten und Quittungen durchnumerieren
– aber modulo 2 genügt !
Unsichere Kanäle mit folgender Spezifikation:
interface Channel {void send(Data d, boolean b);
// ersetzt (data,bit) durch (d,b)// - aber manchmal auch nicht
Data data;boolean bit; // anfangs false}
Kanal für Nachrichten: msg
Kanal für Quittungen: ack
Sender Empfänger
boolean bit = false; boolean bit = false;
do{ do{ if(ack.bit == bit){ if(msg.bit != bit){
data = produce(); consume(msg.data); bit = !bit;} bit = !bit;}
msg.send(data,bit); ack.send(null,bit);
}while(true); }while(true);
6.4.2 Verteilter wechselseitiger Ausschluß
Zentralisierte Lösungen:
Semaphor durch Kanal simulieren (6.1.1)
Boolesches Semaphor durch Prozeß simulieren,
mit synchroner Kommunikation über 2 Kanäle p,v:
while(true){ p.recv(); v.recv(); }
Benutzung: p.send();... kritischer Abschnittv.send();
Verteilte Lösung: unter den beteiligten Prozessen
eine Marke kreisen lassen – wer
sie besitzt, darf kritischen Abschnitt
ausführen.
0
2
1
= Steuerungs-Prozeß,
läßt die Marke kreisen,
recv(); ...
peer[i].send();
und interagiert lokal mit
seinem Anwendungs-
Prozeß (hier 0,1,2)
Jedes System aus Steuerungs- und Anwendungsprozeß
hat lokale Sperre mit Operationen lock/unlock
Initialisierung bei jedem System: lock();
Nummer eines jeden Systems: me
Jeder Steuerungs-Prozeß verhält sich so:
do{recv(); unlock(); lock(); peer[me1].send();}while(true);
6.4.3 Replizierte Datenhaltung
= Datenobjekt wird in mehreren Kopien bei mehreren Prozessen geführt
Motivation: schnelle und sichere Verfügbarkeit im Netz
Problem: Konsistenzerhaltung bei Datenänderung
Problemlösung: mit Rundsendung (broadcast)
an alle Beteiligten
(replicated data)
Postulierte Operationen:
interface Broadcasting<Msg> { void bsend(Msg msg);
// sende msg an alle Beteiligten einschließlich // Absender (jeder erhält Kopie in privatem Puffer)
Msg recv();// entnimm Nachricht aus Puffer
}
Atomares Senden wird gefordert, d.h. unterschiedliche
Empfangsreihenfolgen bei nebenläufigem Senden
sind ausgeschlossen!
Rechtfertigung: häufig entsprechende Hardware-
Unterstützung, z.B. in Lokalnetzen
Voraussetzung: Nur ein Datenobjekt Data
mit einer Operation op
class Data extends Broadcast<Arg> {public static void op(Arg arg){ bsend(arg); }
... // Daten static void realop(Arg arg) {.....}
// Steuerungs-Prozeß: ... do{Arg arg = recv();
realop(arg);}while(true);
...}
top related