Prüfungsklausur Organisatorisches - Informatik Uni

Werbung
Programmierung und Programmiersprachen
Dr. Claudia Leopold
Institut für Informatik
Abt. Parallelverarbeitung und
Komplexe Systeme
[email protected]
Hauptgebäude, Zi. 2-40
Webseite zur Vorlesung (über Lernserver erreichbar):
http://www.informatik.uni-leipzig.de/~leopold/grundPS.html
Organisatorisches
Übungsbeginn: 17.4. (B-Woche) bzw. 23.4. (A-Woche)
Erstes Übungsblatt: 11.4. im Netz (Lernserver)
Abgabe der Lösungen jeweils 2 Wochen nach Ausgabe,
5 Minuten vor der Vorlesung
Ausnahme: erste Abgabe erst am 2.5.
Übungsschein: mindestens 60% der erreichbaren
Punkte
Prüfungsklausur
im Juli, Termin wird noch bekannt gegeben
Zulassungsbedingungen:
(1) Übungsschein ´Digitale Informationsverarbeitung´ und
(2) Übungsschein ´Programmierung und Programmiersprachen´
Übungen
Mo (A/B)
11.15 - 12.45
SR 3-11
Herr Dr. Richter
Mo (A/B)
13.15 - 14.45
SR 3-11
Herr Dr. Richter
Mo (A/B)
15.15 - 16.45
SR 3-11
Herr Dr. Richter
Di (A/B)
9.15 - 10.45
SR 3-05
Herr Dr. Richter
Mi (A/B)
7.30 - 9.00
HS 8
Herr Wittig
Fr (A/B)
7.30 - 9.00
SR 3-11
Herr Wittig
Fr (A/B)
7.30 - 9.00
SR 3-01
Herr Dr. Gräbe
Verbindliche Anmeldung durch Eintragen in die Liste.
Adressen der Übungsleiter:
[email protected] bzw. wittig@...
Inhalt (Plan)
Fortsetzung des in der Vorlesung ´Digitale Informationsverarbeitung´
begonnenen Überblicks zu Programmiersprachen
1. Objektorientierte Programmierung und Modellierung
-> Hauptteil
2. Parallele und verteilte Programmierung
3. Skriptsprachen
4. Maschinennahe Programmierung
einschl. Aspekte der Implementierung höherer
Programmiersprachen
5. Zusammenfassender Überblick zu Programmiersprachen
Literatur
Wolfgang Küchlin, Andreas Weber: Einführung in die Informatik:
Objektorientiert mit Java, Springer-Verlag, 2000, Kapitel 3,7,8.
Bernd Oesterreich: Objektorientierte Softwareentwicklung:
Analyse und Design mit der Unified Modeling Language,
4. Auflage, Oldenbourg Verlag, 1999.
Bert W. Sebesta: Concepts of Programming Languages, 4. Auflage,
Addison-Wesley, 1999.
Java-Lehrbuch, zum Beispiel:
Guido Krüger: Go to Java 2, 2. Auflage, Addison-Wesley, 1999.
Stefan Middendorf, Reiner Singer: Java: Programmierhandbuch
und Referenz, 2. Auflage, dpunkt-Verlag, 1999.
James Gosling et al.: The Java Language Specification, 2. Auflage,
Sun Press, 2000, online verfügbar.
Weitere Literatur wird im Laufe der Vorlesung genannt.
1. Objektorientierte
Programmierung und
Modellierung
Gliederung
1.1. Grundlegende Konzepte der Objektorientierung
1.2. Objektorientierte Modellierung (UML)
1.3. Einführung in Java
1.4. Objektorientierte Programmierung in Java
1.5. Weitere Aspekte der Java-Programmierung
Ausnahmen
Generisches Programmieren
Programmierung und Modellierung
Programmierung
Softwareentwicklung
Planmäßiges, systematisches
Vorgehen
Arbeitsteilige Entwicklung
Umfangreiche Programme
Analyse/Design vor eigentlicher
Implementierung
Objektorientierung wurde besonders für die Entwicklung
komplexer Softwaresysteme konzipiert
-> Modellierung und Programmierung bilden Einheit
Vorteile OO (vs. imperativ, funktional, logisch):
Beschreibung komplexer, dynamischer Systeme
Erweiterte Möglichkeiten zur Strukturierung von Programmen
1.1. Grundlegende Konzepte der
Objektorientierung
Objektorientierung
OO modelliert die reale Welt als System interagierender Objekte
Objekt = gedankliche oder reale Einheit in der
Umwelt und/oder in Software
Grundlegende Konzepte:
Datenkapselung
Nachrichtenaustausch
Bilden von Klassen
Vererbung
Polymorphie
Dynamisches Binden
Datenkapselung
Objekt umfaßt
Attribute (Zustandsvariablen, Felder, Daten) und
Methoden (Operationen, Funktionen)
Abstrakter Datentyp
Zusammenfassung von Daten und Operationen über diesen
Daten
Implementierung der Datenstrukturen und Operationen ist
außerhalb des Objektes nicht sichtbar
Zugriff auf Daten nur über Operationen (get, set und andere)
Konzept existiert auch in nicht-objektorientierten Sprachen
(z.B. Modula-2)
Beispiel: Objekt
rectangle1
Attribute:
Methoden:
x
y
width
height
10
20
120
75
draw()
delete()
move()
Modifikatoren: private, public
Vorteile der Datenkapselung
Klar definierte Schnittstellen unterstützen arbeitsteilige Programmentwicklung (Programmieren im
Großen)
Implementierungsdetails nur innerhalb des
Objektes sichtbar -> Implementierung kann ohne
Anpassung der übrigen Programmteile geändert
werden (bei gleicher Signatur)
Erleichtert Debugging, da Fehler besser lokalisierbar
Nachrichtenaustausch
Objekte
Nachrichten
Nachrichten
Aufbau einer Nachricht
Empfänger
Methodenname
Argumente
Beispiele: rect.move(20,0), rect.delete()
Senden einer Nachricht bewirkt Aufruf der entsprechenden
Methode des Zielobjektes
Nachrichtenaustausch dient
Übermittlung von Informationen
Inanspruchnahme von Diensten (Client/Server)
Klasse
= Zusammenfassung gleichartiger Objekte
gleiche Attribute, aber unterschiedliche Attributwerte
gleiche Methoden
Osterei
Klasse
Objekte
Klasse umfaßt
Attribute, aber keine Attributwerte
Methoden
(Ausnahme: Klassenvariablen)
Beispiel: Klasse
class Rectangle
{
private int x, y, width, height;
public void move(int dx, int dy) {
x = x + dx;
y = y + dy;
}
public void draw() {...}
public void delete() {...}
}
Instanzierung
Vorgehen bei objektorientierter Programmierung:
1. Definition einer Klasse
einschließlich Implementierung der Methoden
2. Instanzierung
= ´Ableiten´ von Objekten aus der Klasse
Attribute werden angelegt und initialisiert (zum
Beispiel mit default-Werten)
Methoden (einschließlich Implementierung)werden aus
Klassendefinition übernommen
Objekte heißen Exemplar oder Instanz der Klasse
Klasse beschreibt Typ des Objekts.
Vererbung
Bei der Definition von Klassen kann man bereits
definierte Klassen als Basis verwenden.
Vorteile: Wiederverwendung von Programmcode,
hierarchische Strukturierung von Programmen,
Erweiterbarkeit
Beispiel:
class coloredRectangle extends Rectangle
{
ink: Color;
public void refill(newInk:Color) {
ink = newInk;
}
}
Oberklasse (Superklasse, Basisklasse): Rectangle
Unterklasse (Subklasse, abgeleitete Klasse): coloredRectangle
Beispiel: Vererbung
blaues Rechteck
Attribute:
x
y
width
height
ink
Methoden:
10
20
120
75
blue
draw()
delete()
move()
refill()
Überschreiben von Methoden
In der Oberklasse bereits implementierte Methoden können
in der Unterklasse mit einer neuen Implementierung
überschrieben werden (engl.: override).
Beide Methoden haben dann den gleichen Namen und die
gleiche Signatur.
Beispiel:
Reimplementierung der Methode draw in coloredRectangle
Aufruf der Methode bewirkt:
Für Objekte der Oberklasse wird die Methode der Oberklasse
ausgeführt.
Für Objekte der Unterklasse wird die Methode der Unterklasse
ausgeführt.
Überladen von Methoden
= Definition von Methoden mit gleichem Namen,
aber unterschiedlicher Signatur
Beispiel:
public void scale(factor: float) {
x = x * factor; y = y * factor;
}
public void scale(factorX: float, factorY: float) {
x = x * factorX; y = y * factorY;
}
Aufruf bewirkt Ausführung der Methode mit den
passenden Parametern
scale(1.3)
vs.
scale(1.2, 3.7)
Polymorphie (Vielgestaltigkeit)
= Methode (gegeben durch Name) kann sich an Kontext
anpassen
Unterscheiden:
statische Polymorphie (Überladen)
auch in nicht-objektorientierten Sprachen, z.B. ´/´ für int
und float
dynamische Polymorphie (Überschreiben)
Verhalten der Methode sollte nur angepaßt, aber nicht
grundsätzlich geändert werden (Gefahr von Programmierfehlern)
Dynamische Polymorphie
Variable kann für Objekte verschiedener Klassen
stehen, sofern eine - eventuell mehrstufige Vererbungsbeziehung besteht .
Beispiel:
rect: Rectangle;
rect := new Rectangle();
rect.draw(); - Aufruf der Methode aus Klasse Rectangle
rect := new coloredRectangle();
rect.draw(); - Aufruf der Methode aus Klasse coloredRectangle
Dynamische Bindung
= Verknüpfung zwischen Methodenaufruf und
auszuführendem Programmcode erfolgt erst zur Laufzeit
Statische Bindung = Verknüpfung erfolgt zur
Übersetzungszeit, durch den Compiler
Vorteil statische Bindung: Geschwindigkeit (schnellere
Programmausführung)
Vorteil dynamische Bindung: Keine Fallunterscheidung
nötig ->
bessere Lesbarkeit
Programm leichter zu modifizieren
Art der Bindung ist durch Programmiersprache festgelegt,
evtl. mit Einflußmöglichkeit durch Programmierer
Arbeiten mit Objekten
Allgemeine Operationen für Objekte:
Erzeugen
Vergleich
Zuweisung
evtl. Löschen (z.B. in C++)
Erzeugenvon Objekten:
durch Konstruktor = spezielle Methode der jeweiligen
Klasse
eventuell überladen
in Java existiert impliziter Konstruktor
Zuweisung von Objekten
An Variablen mit Typ der Oberklasse können Objekte der
Unterklasse zugewiesen werden, aber nicht umgekehrt
Beispiel:
rect: Rectangle := new Rectangle();
cRect: coloredRectangle := new coloredRectangle();
rect := cRect;
cRect := rect;
- zulässig
- verboten
Unterscheiden: deklarierter Typ - tatsächlicher Typ
einer Variablen
Objektidentität vs. Objektgleichheit
rect1: Rectangle := new Rectangle();
rect2: Rectangle := new Rectangle();
rect1
o
Rectangle
rect12
o
Rectangle
Objektgleichheit
(gleiche Initialisierung
oder kopieren der Attr.)
rect1 := rect2;
rect1
o
Rectangle
Objektidentität
rect12
o
Rectangle
(zuweisen)
Abstrakte Klassen
Enthalten deklarierte, aber noch nicht implementierte
Methoden
Instanzierung nicht möglich
Deklarierte Methoden müssen in jeder Unterklasse
vorhanden sein, werden aber unterschiedlich
implementiert
Vorteile: einheitliche Schnittstelle, Client kann unabhängig
von Server programmiert werden
Beispiel:
Geometrische Figur
berechneFläche
Kreis
Rechteck
Dreieck
Vorteile OO
Strukturierung der Programme sehr gut unterstützt
Wiederverwendung, Erweiterbarkeit
siehe auch: abstrakter Datentyp, dynamische Bindung,
abstrakte Klasse
Nachteile OO
Hoher Einarbeitungsaufwand (OO-Denkweise,
Klassenbibliotheken)
Wegen dynamischer Speicherverwaltung oft
höherer Speicherbedarf und längere Laufzeit
1.2. Objektorientierte Modellierung
PPS 1.2-1
Vom Problem zum Programm
Analyse
Einarbeitung in Anwendungsgebiet
Beschreiben von Anwendungsfällen
Erstellen eines objektorientierten Modells der realen Welt
Spezifikation der Funktionalität des künftigen Softwaresystems
Annahme einer perfekten Technik
Entwurf
Übertragung des Modells der realen Welt in die Welt der Software
Berücksichtigung der vorhandenen Technik und Programmiersprache
Algorithmische Beschreibung der Funktionalität
Implementierung
Software-Architektur wird zum realen Programm
PPS 1.2-2
Unified Modeling Language (UML)
Sprache und grafische Notation zur Spezifikation,
Visualisierung, Konstruktion und Dokumentation von
(Software)systemen
Durchgängige Unterstützung für Analyse und Design
durch aufeinander abgestimmte Modelltypen
Anwendungsfalldiagramm
Klassendiagramm
Kollaborationsdiagramm
Sequenzdiagramm
und andere
Geeignet für objektorientierte Softwareentwicklung
UML ist keine Programmiersprache!
Aber ex. Werkzeuge, die automatische Codeerzeugung unterstützen
Vorgehensmodell ist nicht Bestandteil der UML
PPS 1.2-3
Geschichte der UML
Ca. 1989-1994 Forschungsarbeiten zu objektorientierten
Modellierungsansätzen
Darauf aufbauend ab 1994/95 Entwicklung der UML
durch Grady Booch, Jim Rumbaughund Ivar Jacobson
(Firma: Rational Software)
Seit 1995 Unterstützung durch Object Management
Group (OMG) - Entwicklung eines Standards
1996: Version 0.9
Aktuell: Version 1.3
1997: Version 1.0
In Arbeit: Version 2.0
OMG umfaßt >800 Firmen
-> UML ist weit verbreitet
PPS 1.2-4
Klassendiagramm
Beschreibt Klassen und ihre statischen Beziehungen
untereinander
Beziehungen zwischen Klassen stehen stellvertretend für
Beziehungen zwischen Objekten
Darstellung von Klassen kann unterschiedlich detailliert
erfolgen (evtl. Angabe von Typ, Initialwert, Zusicherungen):
Rechteck
Rechteck
Rechteck
anzeigen()
verschieben()
löschen()
Rechteck
x: int = 0
x
y
width
breite: int {breite>0}
höhe: int {höhe<=breite}
anzeigen()
verschieben(dx:int, dy:int)
löschen()
Objekte
Mitunter werden in Klassendiagrammen auch Objekte
dargestellt.
Zur Unterscheidung von Klassennamen werden Objektnamen
unterstrichen.
Evtl. Angabe von zugehöriger Klasse und Attributwerten
Beispiele:
rect: Rechteck
rect
Rechteck
x=0
y=0
:Rechteck
<<
instance of
>>
rect
PPS 1.2-6
Assoziationen
Person
Firma
Firma
besitzt
1
0..*
beschäftigt
0..1
arbeitgeber
0..*
Person
arbeitnehmer
beschäftigt
arbeitet bei
0..1
Schrank
0..*
Person
Assoziationen beschreiben allgemeine Beziehungen
zwischen Objekten
werden auch Benutzt-Beziehungen genannt
möglich: ungerichtete, bidirektionale Beziehungen
PPS 1.2-7
Aggregation
auch: Teil-Ganzes-Beziehung, Hat-Beziehung
Eine Aggregation ist die Zusammensetzung eines
Objektes aus einer Menge von Teilobjekten
ist Spezialfall der Assoziation
Unternehmen
besteht aus
1
1..*
Abteilung
besteht aus
1
besteht aus
Abteilung
1..*
arbeitet für
1..*
Mitarbeiter
Mitarbeiter
1..*
PPS 1.2-8
Komposition
Spezialfall der Aggregation, bei dem die Einzelteile vom
Aggregat existenzabhängig sind
Markierung durch ausgefüllte Raute
Vorderseite
1
hat
Zettel
1
1
hat
Rückseite
1
PPS 1.2-9
Methodenaufrufe bei Aggregationen
Typische Programmstruktur:
Methoden zur Zusammenarbeit mit anderen (´fremden´)
Objekten werden vom Gesamtobjekt zur Verfügung
gestellt
Der Aufruf einer solchen Methode bewirkt den Aufruf
geeigneter Methoden der Teilobjekte.
Dazu enthält die Implementierung der Methode des
Gesamtobjekts entsprechende Methodenaufrufe an die
(im Klassendiagramm nicht sichtbar)
Teilobjekte.
Beispiel: Der Warenwert eines Einkaufskorbes berechnet sich als
Summe der Einzelpreise.
PPS 1.2-10
Rekursive Assoziation
Direkte Rekursion:
Mitarbeiter
name
zimmernummer
manager
sachbearbeiter
*
1
führt
Indirekte Rekursion:
hat
1
*
Patient
familienangehöriger
Person
PPS 1.2-11
Mehrgliedrige Assoziation
Zug
datum
zugnummer
Reservierung
Platz
1..*
1
wagennr
platznr
1..*
Fahrgast
name
Assoziationen zwischen > 3 Klassen analog
Gleiche Klasse kann mehrfach an einer Assoziation
beteiligt sein
PPS 1.2-12
Implementierung von Assoziationen
meist mittels Attributen in den beteiligten Klassen
häufig: Attributname = Rollenname in der Assoziation
gegebenenfalls Verwendung von Arrays oder anderen
Sammlungsklassen
Person
1
besitzt
eigentümer
class Person
{
...
Schrank[] einrichtung;
...
}
0..*
einrichtung
Schrank
class Schrank
{
...
Person eigentümer;
...
}
PPS 1.2-13
Attributierte Assoziation
Assoziation, der Eigenschaften zugeordnet sind
diese Eigenschaften charakterisieren weder die eine noch
die andere Klasse, sondern die Assoziation selbst
Modellierung durch Assoziationsklasse
Unternehmen
1..*
name
anschrift
1..*
Mitarbeiter
name
anschrift
Arbeitsverhältnis
von: Datum
bis: Datum
PPS 1.2-14
Vererbung
auch: Ist-Beziehung
Unterklasse ist Spezialisierung der Oberklasse
Objekte abgeleiteter Klassen sollen jederzeit anstelle von
Objekten ihrer Basisklasse eingesetzt werden können
Oberklasse ist Generalisierung der Unterklasse
Unterscheidungsmerkmal zwischen Ober- und Unterklasse:
Diskriminator
Diskriminator ist ´virtuelles Attribut´ (durch Zugehörigkeit
zur einen oder anderen Unterklasse wird eine Eigenschaft
des Objekts beschrieben)
Zuordnung der Attribute und Methoden zur Ober- oder
Unterklasse sollte nach inhaltlichen Gesichtspunkten
erfolgen (nicht: maximale Wiederverwendung)
PPS 1.2-15
Vererbung - Notation
Diskriminator1
Oberklasse
Diskriminator3
Unterklasse1
Unterklasse5
Diskriminator2
Unterklasse2
Unterklasse3
Unterklasse4
Diskriminator muss nicht angegeben werden
auch bei gleichem Diskriminator sind Einzelpfeile
zulässig
PPS 1.2-16
Vererbung - Beispiel
GeomFigur
{abstrakt}
x,y: int
sichtbar: bool
anzeigen() {abstrakt}
entfernen() {abstrakt}
verschiebeZu(nx,ny)
Figurenform
Kreis
Rechteck
Dreieck
radius {radius > 0}
a {a>0}
b {b>0}
a {0<a<b+c}
b {0<b<a+c}
c {0<c<a+b}
setRadius(r)
anzeigen()
entfernen()
setKanten(a,b)
anzeigen()
entfernen()
setKanten(a,b,c)
anzeigen()
entfernen()
PPS 1.2-17
Quadrat/Rechteck-Problem I
Rechteck
a {a>0}
b {b>0}
setKanten(na,nb)
anzeigen()
entfernen()
Quadrat
{a=b}
Nachteile:
Redundanz (b ist überflüssig)
Zusicherung verwendet Attribute
der Oberklasse -> Einhaltung
durch Methoden der Oberklasse
nicht garantiert (Zusicherung
dort nicht bekannt)
PPS 1.2-18
Quadrat/Rechteck-Problem II
Quadrat
a {a>0}
setA(na)
anzeigen()
entfernen()
Nachteile:
ex. kein Diskriminator
Zuweisung q=r ist zulässig, aber
inhaltlich nicht sinnvoll
Rechteck
b {b>0}
setB(nb)
anzeigen()
entfernen()
-> fehleranfällig
->Ungeeignete Modellierung
PPS 1.2-19
Quadrat/Rechteck-Problem III
Rechteck
a {a>0}
b {b>0}
setKanten(a,b)
anzeigen()
entfernen()
isQuadrat():bool
Beste Variante, hat trotzdem Nachteil
der Redundanz
Günstig: Keine Unterscheidung zwischen
Rechtecken, die aufgrund ihrer Kantenlänge ´zufällig´
Quadrate sind und
´richtigen´ (entsprechend klassifizierten) Quadraten
PPS 1.2-20
Klassenhierarchien
GeomFigur
Strecke
Kreis
2dimGeomFigur
Rechteck
Dreieck
Kugel
3dimGeomFigur
Quader
abstrakte Klasse
konkrete Klasse
PPS 1.2-21
Mehrfachvererbung
Klasse kann mehr als eine Oberklasse besitzen
Einfachvererbung - Klassenhierarchie,
Mehrfachvererbung - azyklischer Graph
Fahrzeug
name
Wasserfahrzeug
Windgetriebenes
Fahrzeug
Segelboot
Mehrfachvererbung ist problematisch
PPS 1.2-22
Klassenattribute
Beschreiben Eigenschaft der Klasse
Alle Objekte der Klasse haben Zugriff auf dieses Attribut
(lesen den gleichen Wert)
weiterhin ex. Klassenmethoden
Haus
anzHäuser
adresse
getAnzHäuser()
getAdresse
PPS 1.2-23
Vom Problem zum Modell
1) Grammatikalische Inspektion der Spezifikation
Substantive - Klassen, Objekte
Verben - Methoden
´hat ein´, ´besteht aus´ - Aggregationen
´ist ein´ - Vererbungsbeziehungen
2) CRC-Karten
Class-Responsibilities-Collaborators =
Klasse - Verantwortlichkeiten - Beteiligte
3) Analyse von Anwendungsfällen
engl.: use case
PPS 1.2-24
Anwendungsfall
beschreibt externes Systemverhalten in begrenzter
Arbeitssituation
beschreibt was das System leisten soll, aber nicht wie
Anwendungsfall umfaßt meist mehrere Varianten, die als
Szenarien bezeichnet werden
Anwendungsfall wird durch Akteur (häufig Nutzer in
bestimmter Rolle) initiiert und führt zu außerhalb des
Systems sichtbarem Ergebnis
Einsatz in Analysephase: Erfassen der Aufgabenstellung
und Abstimmung mit dem Auftraggeber
PPS 1.2-25
Beschreibung eines Anwendungsfalls
Umfaßt (teils optional):
Akteure
Vor- und Nachbedingungen, Invarianten
Nicht-funktionale Anforderungen (z.B. Antwortzeit, Priorität)
Ablaufbeschreibung (wichtigster Teil, stets vorhanden)
Ausnahmen, Fehlersituationen
Variationen
Dienste (notwendige Klassen, Methoden - für späteres Design)
Verfasser, verwendete Materialien
Offene Fragen, Alternativen, Entwurfsentscheidungen
Verweise auf verwandte Diagramme
PPS 1.2-26
Anwendungsfall - Beispiel
Af2
Vertrag schließen und Kfz-Übergabe
Akteure:
Kunde, Kundenbetreuer
Auslöser:
Kunde möchte sein reserviertes Kfz abholen
Ablauf:
1. Reservierung identifizieren
2. Vertrag erstellen
3. Kfz übergeben
PPS 1.2-27
Anwendungsfalldiagramm
Übersicht zu den verschiedenen Anwendungsfällen
beschreibt Beziehungen zwischen Akteuren und
Anwendungsfällen
Buchausleihe
(
.| .
verlängern
.| .
(
Nutzer
ausleihen
.| .
(
Bibliothekar
registrieren
Besucher
recherchieren
PPS 1.2-28
Verhaltensdiagramme
beschreiben zeitabhängiges Verhalten des Systems
unterscheiden:
Zustandsdiagramm
Zustände und Zustandsübergänge des einzelnen Objekts
Aktivitätsdiagramm
Beschreibung von Abläufen in verschiedenem Kontext
Kollaborationsdiagramm
Zusammenarbeit zwischen Objekten, Betonung Beziehungen
Sequenzdiagramm
Zusammenarbeit zwischen Objekten, Betonung Zeit
PPS 1.2-29
Zustandsdiagramm
zeigt für ein Objekt die Folge der möglichen Zustände
und Zustandsübergänge
Beschreibung durch endlichen Automat
.
Beispiel: Objekt = Ticket
Benutzt
ausgeben
abgelaufen
Verfügbar
reserv.
Reserviert
kaufen
Verkauft
absagen
zurückgeben
PPS 1.2-30
Aktivitätsdiagramm
zur Beschreibung von Abläufen in verschiedenem Kontext
beschreibt Ausführungsreihenfolge von Aktivitäten
parallel oder sequentiell
nächste Aktivität kann vom Ergebnis der vorherigen
abhängen
Aktivitäten können Methoden oder komplexere
Operationen sein
eventuell Zuordnung der Aktivitäten zur ausführenden
Klasse
PPS 1.2-31
Kollaborationsdiagramm
beschreibt Zusammenarbeit zwischen Objekten in
begrenzter Situation (z.B. Anwendungsfall)
beschreibt Nachrichtenaustausch einschließlich
Datenaustausch (Argumente der Methoden)
im Gegensatz zum Sequenzdiagramm stehen die
Beziehungen zwischen den Objekten und nicht der
zeitliche Verlauf im Vordergrund
für den Nachrichtenaustausch benötigt der Sender einen
Verweis auf den Empfänger :
Assoziation vom Sender zum Empfänger
Verweis wird durch Nachrichtenaustausch übermittelt
Empfänger ist neu erzeugtes Objekt
Empfänger = Sender
PPS 1.2-32
Kollaborationsdiagramm - Beispiel
<<
parameter
>>
b
:Bestellung
1.1.*[i=1..*]: bpos:=gibBestellPos()
...
1:reserviere(b)
:Reservierung
1.1.3: bpos:=reserviere(artikel,anzahl)
1.1.1: artikel:=gibArtikel()
1.1.2: anzahl:=gibAnzahl()
:Lager
<<
local >> bpos
:Bestellposition
PPS 1.2-33
Kollaborationsdiagramm - Notation
Syntax der Nachrichtenbezeichnung:
[vorgängerBedingung /][sequenzausdruck] : [antwort :=]
methodenname (parameterliste)
sequenzausdruck beschreibt Reihenfolge der Nachrichten
Nachrichten, die während der Bearbeitung der Nachricht Nummer x
gesendet werden, erhalten Nummern x.1, x.2 usw.
vorgängerBedingung ist Aufzählung der Nachrichten, die
vorher gesendet werden müssen (Bsp. 2.3, 3.1/ 4.2:)
´*´ bezeichnet wiederholtes Senden der gleichen
Nachricht
Paralleles Senden: 1.2.*||[i:=1..n]:
Bedingtes Senden: 1.2.* [i>5]:
PPS 1.2-34
Sequenzdiagramm
stellt gleiche Information wie Kollaborationsdiagramm
dar, aber mit Betonung des zeitlichen Ablaufs
objekt 1
Selbstdelegation
new()
objekt 2
objekt 1
nachricht()
antwort
delete()
PPS 1.2-35
Sequenzdiagramm - Beispiel
:Reservierung
reserviere(b)
b:Bestellung
bpos:Bestellposition
:Lager
* gibBestellPos()
bpos
* gibArtikel()
artikel
* gibAnzahl()
anzahl
reserviere(artikel, anzahl)
PPS 1.2-36
Formen des Nachrichtenaustauschs
Synchronmit Rückantwort (auch: sequentiell, Normalfall in
Sender wartet, bis
Methodenausführung beendet
objektorientierter Programmierung):
Synchron ohne Rückantwort: Sender wartet, bis
Empfänger die Nachricht angenommen hat
Asynchron: Nachricht wird an Warteschlange des
Empfängers geschickt, Sender arbeitet sofort weiter
Eingeschränkt: Abbruch, falls der Empfänger die
Nachricht nicht sofort annimmt
Zeitabhängig: Abbruch, falls der Empfänger die Nachricht
nicht innerhalb einer vorgegebenen Zeit annimmt
PPS 1.2-37
Zusammenfassung Modellierung
wird überwiegend in Analyse/Design-Phasen eingesetzt
objektorientierte Modellierung ist eine Form der
Modellierung
Modelle sind abstrakte Beschreibungen
der realen Welt
existierender Software
zu konstruierender Software
verschiedene Modelltypen beschreiben verschiedene
Aspekte des Systems und ergänzen einander
Vorgehensmodell bestimmt, welche Modelltypen in
welcher Reihenfolge wie detailliert erstellt werden
(nicht Bestandteil der UML)
PPS 1.2-38
1.3. Einführung in Java
PPS 1.3-1
Objektorientierte Programmiersprachen
erste Ideen gehen zurück auf Simula 67
(Datenabstraktion, Klassen)
erste und rein objektorientierte Sprache: Smalltalk 80
C++: Erweiterung von C um objektorientierte Konstrukte,
erste Version 1984 (danach weiterentwickelt),
umfangreiche Sprache, weit verbreitet
Eiffel (ca. 1990): integriert Zusicherungen, einfacher als
C++, relativ geringe praktische Bedeutung
CLOS (1988): integriert objektorientiertes und
funktionales Programmieren
Weitere Sprachen: Ada 95, Oberon, Modula-3, ...
PPS 1.3-2
Entwicklung von Java
1991-1992 Green-Projekt (James Gosling, Patrick
Naughton), Ziel: Entwicklung von Hard-/Software für
Konsumelektronik -> Interpreter Oak
1992 Firmengründung zur Vermarktung des Prototyps
Star Seven (*7) -> erfolglos
1994 Web Browser HotJava, verwendet Oak
1995 Umbenennung von Oak in Java, Integration in
Netscape Navigator
1996 Java Development Kit 1.0, Gründung von JavaSoft
rasantes Wachstum des Interesses an Java
1998 JDK 1.2, neue Bezeichnung Java 2 Platform
2000 JDK 1.3 (Kestrel-Projekt), Geschwindigkeitsgewinn
PPS 1.3-3
Vorteile von Java
Portabilität
Java Virtual Machine JVM, Java Bytecode
alle Datentypen in Java sind exakt festgelegt
Unterstützung für Code-Mobilität (Applets)
Objektorientierung
C-ähnliche Syntax (keine Zeiger, aber Verweise)
Robustheit
Garbage Collection, Ausnahmebehandlung
Einschränkung automatischer Typkonvertierung
Sicherheitskonzept
Unterstützung für Nebenläufigkeit (Threads)
Unterstützung für grafische Oberflächen
Umfangreiche Klassenbibliothek
PPS 1.3-4
Das JVM-Konzept
Programm
Compiler (javac)
Bytecode
Interpreter (java)
Interpreter
Just-In-Time Compiler
Rechner
(JIT Compiler)
Rechner
PPS 1.3-5
Beispiel: Hello World
Erstellen der Datei Hello.java
public class Hello {
public static void main(String args[]) {
System.out.println("Hello World!");
}
}
Übersetzen des Quelltextes
javac Hello.java -> Hello.class
Ausführen des Programms
java Hello
PPS 1.3-6
Lexikalische Elemente 1
Unicode
Zeichen werden in 2 Byte kodiert
Kompatibel zu ASCII-Zeichensatz
char/String-Konstanten sowie Bezeichner im Programm dürfen
Umlaute und Sonderzeichen enthalten
Bsp.: übertrag und \u00FCbertrag sind identisch
Bezeichner
sollten mit Buchstabe, dürfen auch mit ´_´ oder ´$´ beginnen
Schlüsselwörter sind nicht zulässig
Klassennamen groß, z.B. EineKlasse
Variablen-, Attribut- und Methodennamen klein, z.B. eineMethode
Konstantennamen vollständig groß, z.B. LIMIT
PPS 1.3-7
Lexikalische Elemente 2
Kommentare
// Einzeiliger Kommentar bis Zeilenende
/* MehrzeiligeKommentare dürfen nicht geschachtelt
werden */
/**
* Dokumentationskommentare für javadoc
* beschreiben Methoden etc. verbal und kennzeichnen
* Parameter und Rückgabewerte.
* <i> HTML </i> ist zulässig.
*/
Weitere Unterschiede zu C:
Kein Präprozessor -> kein #define, #include, #ifdef
Zeilen können nicht mit \ verkettet werden
PPS 1.3-8
Primitive Datentypen
boolean
1 bit
true, false
char
16 bits
Unicode-Zeichen
byte
8 bits
ganze Zahl m. Vorz.
short
16 bits
-"-
int
32 bits
-"-
long
64 bits
-"-
float
32 bits
Fließkommazahl
double
64 bits
-"-
Variablen haben stets einen definierten Wert:
Attribute werden mit 0 (bzw. 0.0 etc.) initialisiert
Lokale Variablen -> Datenflußanalyse durch Compiler
PPS 1.3-9
C- vs Java-Datentypen
in Java nicht vorhanden:
Zeiger
Aufzählungstypen (enum)
Verbundtypen (struct und union)
Bitfelder
Typdefinitionen
sizeof-Operator
unsigned, short int, long int
Neu in Java
boolean
NaN = Not A Number (undefiniert, entsteht bei Division durch 0)
POSITIVE_INFINITY, NEGATIVE_INFINITY
PPS 1.3-10
Arrays
Arrays sind spezielle Objekte -> werden zur Laufzeit mit new
erzeugt
Länge wird beim Erzeugen (zur Laufzeit!) festgelegt und kann
danach nicht mehr verändert werden
Zur Laufzeit geprüft: 0 <= indexausdruck < array.length
Automatische Initialisierung
Bilden von Unterklassen nicht möglich
Indextyp ist int
Bsp. 1:
int[] a;
a = new int[100];
//Deklaration
// Erzeugung
Bsp. 2:
boolean[][] b;
b = new boolean[n][m];
Bsp. 3:
int[] a = {5,9,2,3};
int[][] b= { {0}, {1,2}, {1,2,3} }
PPS 1.3-11
Zeichenketten
Zeichenketten sind Objekte der Klassen
java.lang.String - konstante Zeichenketten, oder
java.lang.StringBuffer - veränderliche Zeichenketten
Bsp.: String s1 = "Meine "; // oder: new String("Meine ");
StringBuffer s2 = new StringBuffer("Zeichenkette");
Verkettung und Automatische Konvertierung:
for (int i=1; i<10; i++)
System.out.println(s1+i+"-te"+s2);
Methoden für String: length(), charAt(), equals(), etc.
Methoden für StringBuffer: length(), append(), insert(), etc.
PPS 1.3-12
Typkonvertierung
Erweiternde Konvertierungen:
byte
short
int
long
float
double
char
Erweiternde Konvertierung erfolgt automatisch bei:
Zuweisungen
arithmetischen Operationen
Methodenaufruf (aktuelle vs formale Parameter)
Einschränkende Konvertierung erfordert explizites Casting:
double x=3.0, y=2.0;
int i = (int) (x/y);
PPS 1.3-13
Ausdrücke und Operatoren
Ähnlich C:
Arithmetische Operatoren
Vergleichsoperatoren (Ergebnistyp boolean, auch für
Objekte)
Logische Operatoren (für boolean)
&& bzw. || stehen für Kurzschlußauswertung
& bzw. | stehen für vollständige Auswertung
Bitoperatoren
Zuweisungsoperatoren (=, += etc., erzeugen Ergebnis)
Bedingter Ausdruck (a>0 ? b=a : b=-a)
Operatoren für Objekte: instanceof, new, Zugriff (.)
PPS 1.3-14
Anweisungen
Ähnlich C:
Block
Variablendeklaration
Ausdruck (nur: ++, --, Zuweisung, Methodenaufruf,new)
if, switch (nur boolesche Bedingungen)
while, do-while (nur boolesche Bedingungen)
for
Variablendeklarationen, Komma-Operator zulässig
nur boolesche Bedingungen
break, continue (auch mit Label)
return (Compiler prüft Vorhandensein)
PPS 1.3-15
Blöcke und Variablendeklarationen
Unterscheiden:
Instanzvariablen (Attribute)
Klassenvariablen (Klassenattribute)
Lokale Variablen, Parameter
Jede Variable hat einen (statischen) Typ
Lokale Variablen dürfen in Blöcken deklariert werden
Lokale Variablen dürfen sich nicht gegenseitig
verdecken!
Das Verdecken von Instanz-/Klassenvariablen durch
lokale Variablen und Parameter ist dagegen zulässig
Konstanten werden durch das Schlüsselwort final
gekennzeichnet, z.B. final int LIMIT = 100;
PPS 1.3-16
1.4. Objektorientierte
Programmierung in Java
PPS 1.4-1
Definition von Klassen
[public] class Klassenname {
Attribut- und Methodendefinitionen
}
mit public: Filename = Klassenname.java
ohne public: Zugriff nur innerhalb des Files (Pakets)
möglich
Beispiel:
class Point {
int x, y, color;
void moveTo(int newX, int newY) {
x=newX; y=newY;
}
}
PPS 1.4-2
Erzeugen von Objekten
Erforderlich: 1) Klassendefinition
2) Objektdeklaration (analog Variablendekl.)
3) Objekterzeugung (new)
Beispiel:
//Klassendeklaration siehe vorige Folie
Point punktA; //Objektdeklaration
punktA = new Point(); //Objekterzeugung
Objekterzeugung bewirkt:
Allokierung von Speicherplatz
Rückgabe eines Verweises
Aufruf eines Konstruktors zur Initialisierung des Objekts
PPS 1.4-3
Programmstruktur
Betrachten im weiteren Anwendungen (Applikationen);
daneben existieren Applets
Ein (einfaches) Java-Quellprogramm umfaßt mehrere
java-Dateien, die jeweils in class-Dateien übersetzt
werden (z.B. javac *.java)
In einer Datei (z.B. in Start.java) muß eine Methode mit
der Signatur
public static void main(String[] args)
deklariert sein
Bei Aufruf von java Start wird diese Methode aktiviert
main kann dann Objekte anderer Klassen erzeugen und
durch Senden von Nachrichten in die Berechnung
einbeziehen
PPS 1.4-4
Instanzvariablen und -methoden
Zur Unterscheidung von Klassenvariablen/-methoden
werden Attribute in Java häufig als Instanzvariablen und
Methoden als Instanzmethoden bezeichnet
Zugriff auf Instanzvariablen und -methoden erfolgt
durch Anwendung des Punkt-Operators auf das Objekt,
z.B. punktA.color, punktA.moveTo(3,4)
In Java können nur Methoden Programmcode enthalten;
globale Funktionen (wie in C) gibt es nicht
Im Gegensatz zu Funktionen beziehen sich
Instanzmethoden stets auf ein Objekt und damit auf
aktuelle Attributwerte
PPS 1.4-5
Parameterübergabe
Java verwendet call-by-value (Wertübergabe)
Primitive Datentypen können nicht verändert werden
bei Objekten können nur Attribute verändert werden, nicht
das Objekt selbst
Lokale Zuweisungen können durch final verboten werden
void beispiel (int number, final int number2, Point punkt) {
number = 7;// außerhalb der Methode nicht geändert
number2 = 8; // Fehlermeldung
punkt.x = 3; // Änderung auch außerhalb
punkt = new Point(); // außerhalb keine Änderung
punkt.x = 5;// außerhalb keine Änderung
}
PPS 1.4-6
Arrays als Parameter
Bei formalen Parametern kann die Länge des Arrays offen
gelassen werden:
int sum(int[] a) {
int erg = 0;
for (int i=0; i<a.length; i++)
erg += a[i];
return erg;
}
int [] myFeld;
myFeld = new int[10];
int sum = sum(myFeld);
PPS 1.4-7
Konstruktoren
Konstruktoren haben den gleichen Namen wie die Klasse
Konstruktoren haben keinen Ergebnistyp
In einer Klasse können mehrere (überladene)
Konstruktoren definiert sein
Falls ein Konstruktor einen anderen Konstruktor aufruft,
so muß dieser Aufruf die erste Anweisung des
Konstruktors sein
Ist für eine Klasse kein Konstruktor definiert, so wird ein
impliziter Konstruktor verwendet
PPS 1.4-8
Das Schlüsselwort this
this ist einVerweis auf das aktuelle Objekt
Verwendung:
Aufruf einer Methode mit dem aktuellen Objekt als
Parameter, z.B.
anderesObjekt.dessenMethode(this)
Zugriff auf überdeckte Variablen, z.B.
void moveTo(int x, int y) { this.x = x; this.y = y; }
Zugriff auf andere Konstruktoren einer Klasse
this(x,y)
PPS 1.4-9
Beispiel: Konstruktoren
class Point {
int x, y, color;
Point(int x, int y) {
this.x = x; this.y = y; color = 0;
}
Point(int x, int y, int color) {
this(x,y); this.color = color;
}
}
PPS 1.4-10
Klassenvariablen und -methoden
werden durch das Schlüsselwort static gekennzeichnet
Zugriff durch Klasse.variable bzw. Klasse.methode(..)
Gültigkeitsbereich Klassenvariablen = gesamtes Programm
Klassenvariablen werden nur einmal für die Klasse, nicht
für jedes einzelne Objekt angelegt
Anwendung Klassenvariablen: Definition von Konstanten
static final double PI = 3.14;
Klassenmethoden können nicht auf Instanzvariablen und
-methoden ihrer Klasse zugreifen
Anwendung Klassenmethoden: Berechnung
mathematischer Funktionen
PPS 1.4-11
Beispiel: Klassenvariablen
public Kunde {
static private int anzKunden = 0;
String name;
Kunde(String name) {
this.name = name;
anzKunden++;
}
static int gibAnzKunden() {
return anzKunden;
}
}
PPS 1.4-12
Initialisierung von Klassenvariablen
Klassenvariablen werden bei der Deklaration oder durch
statische Konstruktoren initialisiert
In beiden Fällen erfolgt die Wertzuweisung beim Laden
der Klasse
Initialisierungen werden in textueller Reihenfolge
ausgeführt
class Beispiel {
static int i=3;
static int j;
static {
j=3*i;
}
PPS 1.4-13
Vererbung
nur Einfachvererbung möglich
Kennzeichnung durch Schlüsselwort extends
alle Klassen sind Nachfahren der Klasse java.lang.Object
Zugriff auf Oberklasse durch Schlüsselwort super
(Zugriff auf Konstruktoren und überschriebene Methoden)
public class BlinkingPoint extends Point {
boolean blinkt;
public void blinkenAus() {blinkt = false;}
public BlinkingPoint(int x, int y) {
super(x,y);
this.blinkt = false;
}
}
PPS 1.4-14
Vererbung und Konstruktoren
1) Anlegen des Speicherbereiches, Initialisieren mit 0
2) Aufruf des passenden Konstruktors, dabei rekursive
Anwendung der folgenden Regeln:
a) Falls der Konstruktor mit einem Aufruf von super (oder this)
beginnt, zunächst Aufruf des entsprechenden Konstruktors
b) Falls a) nicht zutrifft und die Oberklasse keinen expliziten
Konstruktor enthält, Aufruf des Default-Konstruktors der
Oberklasse
c) Falls a), b) nicht zutrifft und die Oberklasse einen
parameterlosen Konstruktor enthält, Aufruf dieses
Konstruktors
d) Falls a), b), c) nicht zutrifft -> Fehlermeldung
3) Initialisierung der Attribute und lokalen Variablen des
Konstruktors, falls Deklaration mit Zuweisung verbunden
4) Ausführung der Anweisungen des Konstruktors
PPS 1.4-15
Vererbung und Überladen
Überladene Methoden müssen sich in den Parametern
(nicht nur im Ergebnistyp) voneinander unterscheiden
Die Auswahl der Methode erfolgt zur Übersetzungszeit
Falls eindeutig bestimmt, wird die Methode mit den
passenden Parametern (Anzahl, Typ) ausgewählt
Falls die Parameter verschiedener Methoden in
Vererbungsbeziehung zueinander stehen oder
anderweitig eine Typkonvertierung möglich ist, wird die
Methode mit den speziellsten Parametern ausgewählt
// Son sei Unterklasse von Father
Son son = new Son();
public void test (Father father) {...};
public void test (Son son) {...};
test(son); // bewirkt Aufruf der Son-Variante
PPS 1.4-16
Beispiel 1 zum Überladen
public class Aufrufer {
public void test(Son son) {...}
// Son-Variante
public void test(Father father) {...} // Father-Variante
}
public class Bsp {
public static void main(String args[]) {
Son son = new Son(); // Son sei Unterklasse von Father
Father father = son;
Aufrufer aufrufer = new Aufrufer();
aufrufer.test(father);
}
}
Auswahl der Methode zur Übersetzungszeit
-> Auswahl nach statischem Typ
-> Es wird die Father-Variante von test aufgerufen
PPS 1.4-17
Beispiel 2 zum Überladen
public class Aufrufer {
public void test(Father father) {...}
// Bei nachträglichem Hinzufügen ohne Neuübersetzung von
// Bsp.java nicht berücksichtigt:
public void test(Son son) {...}
}
public class Bsp {
public static void main(String args[]) {
Son son = new Son();
Aufrufer aufrufer = new Aufrufer();
aufrufer.test(son);
}
}
PPS 1.4-18
Überdecken von Variablen
Vererbung kann zum Überdecken von Instanzvariablen
führen
class Point {
int x, y, color;
...
}
class RealPoint extends Point {
float x, y, color;
...
}
Überdeckte Variablen sind lebendig, aber nicht sichtbar
Zugriff durch super möglich
Auswahl erfolgt zur Übersetzungszeit (laut statischem Typ)
Überdecken von Variablen sollte vermieden werden
PPS 1.4-19
Beispiele zum Überdecken
Bsp.1
class Point {
int x, y, color;
...
}
class RealPoint extends Point {
float x, y, color;
int i = super.x;
...
}
Bsp.2
RealPoint rp = new RealPoint();
Point p = rp;
float f = rp.x;
int i = p.x; // Auswahl laut statischem Typ
PPS 1.4-20
Typkonvertierung für Objekte
Änderung des für den Compiler relevanten Typs
RealPoint rp = new RealPoint();
Point p = rp;
RealPoint rp2 = p;
// Fehlermeldung des Compilers
RealPoint rp2 = (RealPoint) p;
Voraussetzung: neuer Typ = dynamischer Typ oder
neuer Typ = Oberklasse des dynamischen Typs
Andernfalls wird zur Laufzeit eine Ausnahme ausgelöst
Dieser Fall sollte durch Verwendung von instanceof
vermieden werden
if (p instanceof RealPoint)
RealPoint rp2 = (RealPoint) p;
PPS 1.4-21
Beispiel 1 zur Typkonvertierung
Zugriff auf Methoden und Attribute, die nur in der
Unterklasse definiert sind
class BlinkingPoint extends Point {
boolean blinkt;
public void blinkenAus() {...}
}
...
BlinkingPoint bp = new BlinkingPoint();
Point p = bp;
if (((BlinkingPoint) p).blinkt)
((BlinkingPoint) p).blinkenAus();
PPS 1.4-22
Beispiel 2 zur Typkonvertierung
Zugriff auf überdeckte Variablen
class Point {
int x, y, color;
...
}
class RealPoint extends Point {
float x, y, color;
...
}
...
RealPoint rp = new RealPoint();
Point p = rp;
int i = ((Point) rp).x;
float f = ((RealPoint) p).x;
PPS 1.4-23
Überschreiben, Überladen und Überdecken
Überschreiben und Überladen beziehen sich auf Methoden;
Überdecken bezieht sich auf Attribute
beim Überschreiben haben alle Parameter den gleichen Typ,
beim Überladen gibt es Unterschiede
gleiche Parametertypen, aber unterschiedlicher Ergebnistyp
-> Fehlermeldung durch Compiler
überschriebene Methoden werden dynamisch gebunden,
überdeckte Attribute werden statisch gebunden
Konsequenz: bei Methoden ist kein Typcast nötig, falls neuer
Typ = dynamischer Typ
Klassenmethoden werden nicht überschrieben, sondern neu
definiert
Klassen- und Instanzmethoden mit gleicher Signatur sind
nicht zulässig
PPS 1.4-24
Beispiel zum Überschreiben, -laden, -decken
class Point {
int x = 0, y = 0;
void move(int dx, int dy) { x += dx; y += dy; }
int color;
}
class RealPoint extends Point {
float x = 0.0f, y = 0.0f;
void move(int dx, int dy) { move((float) dx, (float) dy); }
void move(float dx, float dy) { x += dx; y += dy; }
}
PPS 1.4-25
Wrapper-Klassen
Jedem primitiven Typ ist eine Wrapper-Klasse
zugeordnet: int - Integer, float - Float etc.
Nutzen:
Die Wrapperklassen sind Unterklassen von Object und
stellen zusätzliche Methoden zur Verfügung
float f = 1.23f;
String s = Float.toString(f)
Viele Methoden (z.B. der Klasse Vector) verlangen als
Parameter Objekte
Keine automatische Konvertierung
myVector.addElement(new Integer(7));
PPS 1.4-26
Das Schlüsselwort final
bei Instanzvariablen, Klassenvariablen, lokalen Variablen:
Definition von Konstanten
Sicherstellen einer nur einmaligen Wertzuweisung
bei Parametern: Verbot lokaler Zuweisungen
bei Klassen: Verbot der Bildung von Unterklassen
bei Methoden: Verbot des Überschreibens
Nutzen (bei Klassen und Methoden):
Vermeiden von Fehlern (versehentliches Überschreiben)
Effizientere Implementierung (da statische Bindung
möglich)
PPS 1.4-27
Pakete
Kennzeichnung durch package paketname; als erste
Anweisung in allen Klassen des Pakets
Nutzen: Strukturierung des Programms:
Gruppieren von Quellfiles
getrennte Namensräume
Pakete können Klassen und/oder Unterpakete enthalten
Paketstruktur entspricht Verzeichnisstruktur
Paketname = Verzeichnisname
Bezeichnung für Unterpakete: grossesPaket.unterpaket
Klassen ohne package-Anweisung gehören alle zur
gleichen (namenlosen) Klasse
Pakete können archiviert werden (jar)
PPS 1.4-28
Import-Anweisung
Import aller Klassen eines Paketes durch
import paketname.*
(als erste Anweisung hinter package, sofern vorhanden)
Import einer bestimmten Klasse durch
import paketname.Klassenname
Import eines Paketes impliziert nicht den Import der
Unterpakete
auch ohne Import-Anweisung kann über
paketname.Klassenname.methode()
auf fremde Klassen zugegriffen werden
Import kann Datenkapselung nicht aufheben
java.lang.* wird automatisch importiert
PPS 1.4-29
Datenkapselung
für Methoden und Attribute:
private, public, protected, default
Klasse
Unterklasse
Paket
default
X
(gl. Paket)
X
private
X
protected
X
X
X
public
X
X
X
Welt
X
für Klassen: public, default
default - nur innerhalb des Pakets sichtbar
public - überall sichtbar
Klasse nicht sichtbar -> Attribute/Methoden nicht
sichtbar (unabhängig von deren Modifikator)
PPS 1.4-30
Datenkapselung - private
Als private gekennzeichnete Attribute / Methoden
sind für Objekte anderer Klassen nicht sichtbar
Trotzdem können die verschiedenen Objekte der
gleichen Klasse gegenseitig auf ihre privaten
Attribute/ Methoden zugreifen
Als private gekennzeichnete Attribute / Methoden
werden nicht vererbt
Falls in der Unterklasse Attribute/Methoden mit
gleichem Namen definiert werden, so handelt es
sich um eine Neudefinition (kein Überschreiben,
Überladen, Überdecken)
PPS 1.4-31
Datenkapselung - public
package paketA;
package paketB;
public class One {
import paketA.One;
public int a;
public class Four extends One {
}
... = a ...
public class Two extends One { }
...
public class Five {
}
... = one.a ...
public class Three {
}
...
}
PPS 1.4-32
Datenkapselung - protected
package paketA;
package paketB;
public class One {
import paketA.One;
public int a;
public class Four extends One {
}
... = a ...
public class Two extends One { }
...
public class Five {
}
... = one.a ...
public class Three {
}
...
}
PPS 1.4-33
Datenkapselung - default
package paketA;
package paketB;
public class One {
import paketA.One;
public int a;
public class Four extends One {
}
... = a ...
public class Two extends One { }
...
public class Five {
}
... = one.a ...
public class Three {
}
...
}
PPS 1.4-34
Datenkapselung und Vererbung
Beim Überschreiben ist es meist sinnvoll, die
Zugriffsklasse beizubehalten.
Falls doch Änderung, darf die Unterklasse die
Sichtbarkeit erweitern, aber nicht einschränken, d.h.
Oberklasse public -> Unterklasse public
Oberklasse protected -> Unterklasse protected oder public
Oberklasse default -> Unterklasse default, public oder protected
Bei Überladen, Überdecken und Neudefinition gibt es
keine solchen Einschränkungen
PPS 1.4-35
Abstrakte Klassen
Klassen müssen als abstract gekennzeichnet werden,
wenn sie mindestens eine abstrakte Methode definieren
oder erben
Abstrakte Methoden beschreiben Schnittstellen (Signatur)
Abstrakte Methoden müssen in Unterklassen
überschrieben (implementiert) werden, erst dann ist
Instanzierung möglich
Konsequenz: abstract kann nicht mit final, static, private
kombiniert werden
abstract class Fahrzeug() {
...
abstract void starte();
}
class Fahrrad extends Fahrzeug {
void starte() {
steigeAuf();
}
}
PPS 1.4-36
Interfaces
auch: Schnittstelle, Schnittstellenklasse
Interfaces sind spezielle Klassen, die nur abstrakte
Methoden und Konstanten enthalten
explizite Kennzeichnung als public abstract
beziehungsweise public final static kann entfallen
möglich: public, default
falls public: Filename = Name des Interfaces .java
public interface KannBlinken {
void blinkenEin();
void blinkenAus();
}
public interface KannVerschieben {
int GRENZE = 100;
boolean move(int dx, int dy);
}
PPS 1.4-37
Implementierung von Interfaces
Eine Klasse kann ein oder mehrere Interfaces
implementieren
Dazu muß sie
die Interfaces unter implements aufführen und
alle Methoden der Interfaces überschreiben (falls nur
einige überschrieben werden, bleibt die Klasse abstrakt)
Interfaces ermöglichen also Mehrfachvererbung für den
wichtigen Spezialfall abstrakter Methoden
Bei Namenskonflikten erhalten beide abstrakten
Methoden die gleiche Implementierung - für sinnvolle
Verwendung ist der Programmierer verantwortlich
PPS 1.4-38
Beispiel: Interfaces
public class BlinkingPoint extends GeomFigur implements
KannBlinken, KannVerschieben {
boolean blinkt;
int x, y;
public void blinkenEin() { blinkt = true; }
public void blinkenAus() { blinkt = false; }
public boolean move(int dx, int dy) {
x+=dx; y+=dy;
if (x > GRENZE || y > GRENZE )
return false;
else return true;
}
PPS 1.4-39
Verwendung von Interfaces und abstrakten Klassen
Möglich: Deklaration von Variablen mit dem Typ eines
Interfaces/einer abstrakten Klasse
Diesen Variablen können Objekte aller Klassen
zugewiesen werden, die das Interface implementieren
Der Compiler akzeptiert dann den Aufruf der Methoden
des Interfaces
Analog: Interfaces/abstrakte Klassen als Elementtyp von
Feldern bzw. Typ formaler Parameter
Typcast, instanceof sind anwendbar
KannBlinken leuchtObjekt;
if (...) leuchtObjekt = new BlinkingPoint();
else leuchtObjekt = new BlinkingArrow();
leuchtObjekt.blinkenEin();
// Nicht zulässig ist leuchtObjekt.move(3,4);
PPS 1.4-40
Interfaces und Vererbung
Bei implementierenden Klassen:
Die Eigenschaft, ein Interface zu implementieren, wird
vererbt, muß also in Unterklassen nicht erneut deklariert
werden
Zwischen Interfaces:
Interfaces können Unterklasse von ein oder mehreren
anderen Interfaces sein (hierarchisch)
Für diese Form der Vererbung wird das Schlüsselwort
extends verwendet
PPS 1.4-41
Generisches Programmieren
Programmieren auf hohem Abstraktionsniveau
Programmiertechnik, die in Java mit bereits bekannten
Mitteln (Interfaces, Überschreiben) realisiert wird
Nutzen: Wiederverwendung von Programmcode
Generische Datentypen (z.B. Liste, Stack) verwenden als
Elementtyp Object (oder anderen abstrakten Typ)
Einfügen etc. kann unabhängig vom konkreten Elementtyp
("generisch") programmiert werden
Generische Methoden verwenden als Parametertyp
Object (oder anderen abstrakten Typ) und sind damit auf
Objekte beliebiger Klassen anwendbar
intern häufig Aufruf abstrakter Methoden, die in den
Unterklassen überschrieben sind
Verwendung spezieller Methoden erfordert Typcast
PPS 1.4-42
Speicherfreigabe
Der vom Programm benutzte Speicher gliedert sich in
Stack: Lokale Variablen und Parameter der in
Ausführung befindlichen Methoden
Halde (Heap): Objekte
Speicher auf dem Stack wird nach Verlassen der Methode
freigegeben (C und Java)
In C wird Haldenspeicher mit malloc angefordert und
mit free freigegeben -> fehleranfällig
In Java wird Haldenspeicher mit new angefordert und
automatisch freigegeben -> vereinfacht
Programmierung
PPS 1.4-43
Garbage Collector
niedrigpriorisierter Hintergrundprozeß zur
automatischen Freigabe unerreichbarer Objekte
Objekt ist unerreichbar, wenn es keine Verweiskette vom
Stack auf das Objekt mehr gibt
Objekt kann unerreichbar werden durch
Verlassen eines Blocks -> Entfernen Variablen vom Stack
Zuweisungen: p = null oder p = p2
Unerreichbarkeit eines Vorgängerobjekts (z.B. Liste)
GC ruft vor Freigabe die Methode
protected void finalize()
auf, falls vorhanden (Destruktor)
expliziter Aufruf des Garbage Collectors durch System.gc()
PPS 1.4-44
1.5. Ausnahmebehandlung
PPS 1.5-1
Ausnahmen und Fehler
Ausnahmen (Exceptions) sind "leichte" Fehler, nach
denen eine Programmfortsetzung sinnvoll ist oder sein
kann
Fehler (Errors) führen zu Programmabbruch
Throwable
Exception
RuntimeException
NullPointerException
Error
IOException
OutOfMemoryError
FileNotFoundException
PPS 1.5-2
Konzept der Ausnahmebehandlung
Ausnahmen werden häufig von vordefinierten
Java-Methoden ausgelöst und müssen vom Programmierer
behandelt (abgefangen) werden
weiterhin kann der Nutzer eigene Ausnahmen definieren
Abfangen von Ausnahmen durch try-catch
möglich: mehrere catch-Blöcke, finally
try {
// Anweisungsblock, der eine Ausnahme auslösen kann
}
catch (Exception e) {
// Anweisungen zur Behandlung der Ausnahme
}
PPS 1.5-3
Weiterleiten von Ausnahmen
1. Fall: IOException (und eigene Ausnahmen)
in Methode nicht behandelte Ausnahmen müssen unter
throws deklariert werden, sonst Fehlermeldung durch
Compiler
void myMethod() throws ArrayOutOfBoundsException,
MeineException {...}
2. Fall: RuntimeException
können abgefangen werden, müssen aber nicht
Auflistung unter throws kann entfallen
Generell
Ausnahmen wandern die Aufrufhierarchie hinauf bis sie
abgefangen werden
außen angekommen -> Java-Interpreter stoppt
PPS 1.5-4
Beispiel: Abfangen von Ausnahmen
int a, b, c;
// Einlesen von b und c
try {
a = b / c;
}
catch (ArithmeticException e) {
System.out.println("Bitte neuen Divisor eingeben: ");
// erneutes Einlesen von c
}
PPS 1.5-5
Ausnahmen als Objekte
Ausnahmen sind Objekte (enthalten Attribute, Methoden)
alle Ausnahmeklassen sind von Throwable abgeleitet
Klassen charakterisieren die Art der Ausnahme, Objekte
die konkret im Programm aufgetretene Fehlersituation
catch (BspAusnahme e) fängt alle Ausnahmen der Klasse
BspAusnahme und ihrer Unterklassen ab
für alle Ausnahmeklassen definiert:
Konstruktor mit Übergabe einer Fehlermeldung
Konstruktor ohne Übergabe einer Fehlermeldung
Methode getMessage
Definition eigener Ausnahmeklassen durch Bilden einer
Unterklasse von Exception
PPS 1.5-6
Auslösen von Ausnahmen
erfolgt durch throws-Anweisung
Integer value;
public void setValue(Integer value) {
if (value==null)
throw new IllegalArgumentException("null übergeben");
this.value = value;
}
throws wird häufig in catch verwendet, um verschiedene
Ausnahmesituationen zusammenzufassen
beim Überschreiben von Methoden dürfen der
throws-Klausel keine neuen Ausnahmen hinzugefügt
werden; Weglassen von Ausnahmen ist zulässig
PPS 1.5-7
2. Parallele, verteilte und
nebenläufige Programmierung
PPS 2.1-1
Gliederung
2.1. Überblick
Begriffe, Architekturen, Programmiermodelle
2.2. Threadprogrammierung in Java
2.3. Applets
2.4. Remote Method Invocation
Literatur zu 2.1.:
C. Leopold: Parallel and Distributed Computing: A Survey of
Models, Paradigms, and Approaches, Wiley, 2000
Literatur zu 2.2-2.4:
Java-Lehrbücher
PPS 2.1-2
2.1. Überblick
Nebenläufige Programmierung
Kennzeichen: mehrere Programmfäden befinden sich
gleichzeitig in Abarbeitung
Konsequenz: es existieren mehrere Programmzähler
Ausführungsreihenfolge von Operationen aus
verschiedenen Programmfäden ist dem Programmierer
nicht bekannt
kennt nur partielle Ordnung innerhalb eines Programmfadens
Ausführung auf einem Prozessor (Pseudoparallelität) oder
mehreren Prozessoren (Parallelität) möglich
Motivation: Beschreiben probleminhärenter Parallelität
(z.B. Simulationsaufgaben)
PPS 2.1-3
Nebenläufigkeit - Probleme
Programm muß für jede Ausführungsreihenfolge korrekt
arbeiten
Zeitkritischer Ablauf (engl.: race condition): Gleiches
Programm kann auf gleicher Eingabe verschiedene
Ausgaben erzeugen -> vermeiden
Programmfäden nutzen gemeinsame Ressourcen (z.B.
gemeinsame Variablen)
Verklemmung(engl.: deadlock): gegenseitiges Warten
auf Ressourcenfreigabe verhindert Weiterarbeit des
Programms -> vermeiden
PPS 2.1-4
Paralleles Rechnen
Kennzeichen: gleichzeitige Ausführung von
Berechnungen mit Ziel Geschwindigkeitsgewinn
Einsatz mehrerer Prozessoren, die durch Netzwerk
verbunden sind und zur Lösung der Aufgabe kooperieren
parallele Architekturen sind meist homogen, haben oft
gemeinsamen Speicher
Konzentration auf eine Anwendung, d.h., parallele
Operationen sind Teil des gleichen Programms
Kommunikationsstruktur kann häufig statisch geplant
oder zumindest abgeschätzt werden
parallele Programme sind meist nebenläufig
Typisches Anwendungsgebiet: wissenschaftliches
Rechnen
PPS 2.1-5
Verteiltes Rechnen
Kennzeichen: räumliche Verteilung von Berechnungen
auf verschiedene Rechner eines Netzwerkes, zwecks
Nutzung entfernter Ressourcen
Hard- und Softwareressourcen, z.B. Parallelrechner,
Drucker, Datenbanken
Architekturen sind meist heterogen und dynamisch, haben
keinen gemeinsamen Speicher
betrachtet System aus mehreren, getrennt entwickelten,
Anwendungen, die gemeinsame Ressourcen nutzen und
eventuell kooperieren
=> Paralleles, verteiltes und nebenläufiges Rechnen sind
verwandte Gebiete mit vielen Überschneidungen und
Gemeinsamkeiten
PPS 2.1-6
Architektur 1: Feldrechner
Steuerrechner
PPS 2.1-7
Architektur 2: Parallelrechner mit
gemeinsamem Speicher
Gemeinsamer Speicher
P
P
P
P
P
P
M
M
M
M
M
M
PPS 2.1-8
Architektur 3: Parallelrechner mit
verteiltem Speicher
P
P
P
M
M
M
P
P
P
M
M
M
P
P
P
M
M
M
PPS 2.1-9
Architektur 4: Verteiltes System
PPS 2.1-10
Datenparallelität
paralleles Programmiermodell
Grundidee: parallele Anwendung der gleichen Operation
auf verschiedene Daten
Daten werden auf Prozessoren (Speicher) verteilt
Einfache Variante (Feldrechner): Operationen sind
elementar -> nur ein Programmzähler
Erweiterte Variante (Parallelrechner): Operationen sind
komplex, aber unabhängig voneinander
keine Kommunikation während der Ausführung einer Operation
nach Operationsausführung Synchronisation
Sprachen: High Performance Fortran, HPF-2, C*, HPJava
PPS 2.1-11
Datenparallelität - Beispiel
!HPF$ INDEPENDENT
Begin
FORALL (I=1:3)
a(I) = b(I)
b(1)
b(2)
b(3)
a(1)
a(2)
a(3)
d(1)
d(2)
d(3)
c(1)
c(2)
c(3)
c(I) = d(I)
END FORALL
End
PPS 2.1-12
Gemeinsamer Speicher (Programmiermodell)
Thread
Thread
Thread
Thread
Gemeinsamer
Speicher
Thread
Thread
Programmfäden (Threads) kommunizieren indirekt
durch Lesen/Schreiben gemeinsamer Variablen
Zeitkritische Abläufe und Deadlocks müssen durch
Synchronisation vermieden werden
Gemeinsamer Speicher kann physisch existieren oder
durch Software nachgebildet werden
für nebenläufige und parallele Programmierung
PPS 2.1-13
Gemeinsamer Speicher - Formen
Thread-Programmierung (z.B. Pthreads, Java Threads):
explizite Erzeugung der Threads und Zuweisung von
Aufgaben durch den Programmierer
Sprachkonstrukte zur Synchronisation und
Beeinflussung des Scheduling
Scheduling = räumliche und zeitliche Zuordnung der Threads zu
Prozessoren
Direktivenbasierte Programmierung (z.B. OpenMP):
Compiler übernimmt Threaderzeugung und
Aufgabenverteilung
Programmierer beschreibt Parallelitätspotential und
notwendige Synchronisationen problemnah (z.B. durch
parallele Schleifen)
PPS 2.1-14
Nachrichtenaustausch
engl.: message passing
Begriff hat andere Bedeutung als im OO-Programmieren!
Prozesse kommunizieren durch Senden und Empfangen
von Nachrichten, es existiert kein gemeinsamer Speicher
Kommunikation kommt nur zustande, wenn passende
Sende- und Empfangsoperationen ausgelöst wurden
Kommunikation erfolgt zwischen 2 Prozessen, muß
statisch geplant werden und impliziert Synchronisation
wichtigstes Modell der parallelen Programmierung
Bibliotheken: Message Passing Interface, MPI-2, PVM
PPS 2.1-15
Nachrichtenaustausch - Beispiel
char msg[20];
int me, total, tag;
MPI_Status status;
...
MPI_Comm_rank(MPI_COMM_WORLD, &me);
MPI_Comm_size(MPI_COMM_WORLD, &total);
if (me==0) {
strcpy(msg, "Gruesse von Prozess 0");
MPI_Send(msg, strlen(msg)+1, MPI_CHAR, 1, tag, MPI_COMM_WORLD);
}
else if (me==1) {
MPI_Recv(msg, 20, MPI_CHAR, 0, tag, MPI_COMM_WORLD, &status);
...
}
PPS 2.1-16
Client/Server
wichtigstes Paradigma des verteilten Rechnens
beschreibt asymmetrische Beziehung zwischen Prozessen
Netzwerk
Client
Server
Ressource
Klienten können auf Ressource nur über die vom Server
angebotenen Dienste zugreifen
Server ist passiver Dienstanbieter
Client ist aktive Seite, löst Interaktion aus
während Ausführung des Dienstes wartet Client
PPS 2.1-17
Client/Server 2
Client und Server können getrennt entwickelt werden
meist existieren mehrere Klienten pro Server
-> Diese können unter Verwendung von Threads
gleichzeitig bedient werden!
möglich:
hierarchische Anordnung: Server nutzt während der
Dienstausführung Dienste eines anderen Servers
gleicher Rechner übernimmt (je nach Kontext) Rolle
des Clients oder Servers - > Peer-to-Peer
Programmierung mittels Sockets, Remote Procedure
Call, Remote Method Invocation
PPS 2.1-18
Mobiler Code
Gegenstück zum Datenaustausch zwischen Prozessen
Analogie: Versenden von Briefen vs. Reisen
Hauptproblem: Sicherheit
Varianten:
Austausch von Programmtexten
Migration in Abarbeitung befindlicher Prozesse
Einsatzgebiete:
Erweiterungen des Client/Server-Modells
Mobile Agenten
Parallele Mobile Agenten
Automatische Migration
PPS 2.1-19
Mobiler Code - Einsatzgebiete
Erweiterungen des Client/Server-Modells:
Remote Evaluation: Code wird zur Laufzeit vom Client
zum Server geschickt (z.B. Übermittlung einer Funktion zwecks
Berechnung durch leistungsfähigen Server)
Code on Demand: Server verwaltet Datenbank mit
Programmtexten und versendet sie bei Bedarf an die
Klienten (Beispiel: Applets in Webseite)
Mobile Agenten: Programm wandert während seiner
Ausführung durch Netzwerk zwecks Nutzung entfernter
Ressourcen; Programm entscheidet selbst, wann und
wohin es migriert
Agenten können kooperieren
PPS 2.1-20
Messaging
auch: Message-Oriented Middleware (MOM), z.B. Java Message
Service API
Verteilte Prozesse kommunizieren über gemeinsamen
Speicher -> ermöglicht zeitliche Entkopplung von
Sender und Empfänger
Varianten:
Message Queuing: Als gemeinsamer Speicher dienen
Schlangen (Queues), in die Nachrichten eingefügt bzw.
aus denen Nachrichten entnommen werden können
im System existieren meist mehrere Schlangen mit
unterschiedlichen Zugriffsrechten
Publish-and-Subscribe: Produzenten stellen Klassen
von Informationen zur Verfügung, Konsumenten
können diese abonnieren (vergleichbar Mailinglisten)
PPS 2.1-21
Verteilte Objekte
Verteiltes Programmiermodell - betrachten Objekte, die
sich auf verschiedenen Rechnern befinden (-> getrennte
Adreßräume)
Konzept: verbinden mit jedem Objekt einen eigenen
Prozeß (Unterschied zu sequentiellem Java und Threads!)
Prozeß verwaltet das Objekt im Sinne eines Servers
andere Prozesse können den Programmcode nicht
selbst ausführen, sondern müssen dazu die Dienste des
Servers in Anspruch nehmen -> RMI = Remote Method
Invocation = entfernter Methodenaufruf
Systeme: CORBA, Java RMI, DCOM
PPS 2.1-22
2.2. Java Threads
Besonderheit Java: Threadprogrammierung ist in die
Sprache integriert
Motivation: Unterstützung nebenläufiger (nur sekundär
paralleler) Programmierung
Ein Programm (d.h., ein Prozeß des Betriebssystems)
kann mehrere Threads umfassen
Die Threads eines Programmes verfügen über
gemeinsamen Speicher
daneben existieren lokale Variablen der Threads
Alle Threads arbeiten mit dem gleichen Programmtext,
aber unterschiedlichen Programmzählern
- > typisch: Verschiedene Threads bearbeiten verschiedene Methoden
PPS 2.1-23
Threaderzeugung mittels Thread
Die Klasse Thread des Pakets java.lang definiert
Methoden zur Arbeit mit Threads: run, start, etc.
Threaderzeugung mittels Thread:
Bilden einer Unterklasse von Thread
Überschreiben der vordefinierten Methode run
mit der gewünschten Funktionalität des Threads
Aufruf der von Thread geerbten Methode start
-> bewirkt Start des Threads und impliziten Aufruf von run
PPS 2.1-24
Beispiel 1 zur Threaderzeugung
public class BspThread extends Thread {
...
public void run() {
System.out.println("Gruesse vom erzeugten Thread");
}
}
public class Bsp {
public static void main(String[] args) {
BspThread t = new BspThread();
t.start();
System.out.println("Gruesse vom Hauptprogramm");
}
}
PPS 2.1-25
Threaderzeugung mittels Runnable
Da Java nur Einfachvererbung erlaubt, schließt die vorige
Methode Vererbung nach inhaltlichen Aspekten aus
Threaderzeugung mittels Runnable ist flexibler (aber etwas
komplizierter):
Runnable ist vordefiniertes Interface, enthält nur eine
Methode: void run()
Aufrufende Klasse erzeugt zwei Objekte: Nutzer-Thread
einer eigenen Klasse und Hilfs-Thread der Klasse Thread
Klasse des Nutzer-Threads implementiert Runnable
Bei Erzeugung des Hilfs-Threads Übergabe des
Nutzerobjekts als Argument des Konstruktors
Aufruf der Methode start des Thread-Objekts
PPS 2.1-26
Beispiel 2 zur Threaderzeugung
public class NutzerThread extends ... implements Runnable {
public void run() {
System.out.println("Gruesse vom erzeugten Thread");
}
}
public class Bsp {
public static void main(String[] args) {
NutzerThread nutzerThread = new NutzerThread();
Thread hilfsThread = new Thread(nutzerThread);
hilfsThread.start();
System.out.println("Gruesse vom Hauptprogramm");
}
}
PPS 2.1-27
Beenden von Threads 1
automatisch am Ende der run-Methode
Direkter Abbruch (stop) durch andere Threads soll in
JDK 1.3 nicht mehr verwendet werden (Problem:
Ressourcenfreigabe)
Andere Threads können durch Aufruf der Methode
public void interrupt()
zum Abbruch auffordern
Thread kann durch
public boolean isInterrupted()
feststellen, ob er zum Abbruch aufgefordert wurde und
gegebenenfalls die run-Methode beenden
PPS 2.1-28
Beenden von Threads 2
Mit join() kann ein Thread auf die Beendigung eines
anderen Threads warten:
public final void join() throws InterruptedException
Threadprogramme sind unstrukturiert: jeder Thread
darf jeden zum Abbruch auffordern
Threads leben eventuell länger als das
Hauptprogramm
Abbruch aller Threads durch System.exit(0)
statt 0 Angabe eines Fehlercodes möglich
System.exit(0) kann in Hauptprogramm oder erzeugtem
Thread aufgerufen werden
PPS 2.1-29
Unterbrechen von Threads
erfolgt mittels der Methode
public static void sleep(long milllis)
Bei Eingang einer Abbruchanforderung während des
Schlafes wird eine Ausnahme ausgelöst und der Thread
sofort geweckt -> Ausnahme abfangen
Aufruf : Thread.sleep(100) - bezieht sich auf den aktuellen
Thread, kann auch das Hauptprogramm sein
Mit
public final boolean isAlive()
kann abgefragt werden, ob ein Thread noch läuft, z.B.
if (t.isAlive()) t.interrupt();
PPS 2.1-30
Beispiel zum Unterbrechen
public class BspThread extends Thread {
public void run() {
while (true) {
if (isInterrupted()) break;
System.out.println("Hallo");
try { Thread.sleep(100); }
catch (InterruptedException e) { interrupt(); }
}
}
}
public class Bsp {...
BspThread t = new BspThread();
t.interrupt();
}
PPS 2.1-31
Synchronisation
Kritischer Bereich:
Abschnitt des Programms, in dem Zugriff auf
gemeinsame Ressourcen erfolgt
darf nicht durch andere Prozesse, die die gleiche
Ressource nutzen, unterbrochen werden
Java-Threads basieren auf dem Monitor-Konzept:
jedem Objekt ist ein Schlüssel (Lock) zugeordnet
Programmierer markiert kritische Bereiche mit dem
Schlüsselwort synchronized
Java-System stellt sicher, daß sich zu einem Zeitpunkt
nur ein Thread in einem kritischen Bereich des gleichen
Objektes befindet
PPS 2.1-32
Locks und Objekte
in Java besteht eine 1:1-Beziehung zwischen Lock und
Objekt
Sinn: gemeinsame Ressourcen sind in Java-Programmen
Attribute und damit einem Objekt zugeordnet
Alle Ressourcen des Objekts werden durch den gleichen
Lock geschützt
Markierung mit synchronized ist möglich für
Methode- es wird der Lock des aktuellen Objekts
angefordert
Anweisungsblock - Programmierer legt explizit fest,
von welchem Objekt der Lock angefordert wird
PPS 2.1-33
Ausschließlicher Zugriff
wird durch das Monitor-Konzept realisiert
Nach Erzeugen eines Objekts ist dessen Lock verfügbar.
Sobald ein Thread einen kritischen Bereich erreicht, wird
automatisch der dazugehörige Lock angefordert.
Falls verfügbar, wird der Lock dem aufrufenden Thread
zugeordnet und ist dann für andere Threads nicht mehr
verfügbar.
Andernfalls wird der Thread in die Warteliste des
angeforderten Locks eingetragen.
Bei Verlassen des kritischen Bereichs wird der Lock
automatisch freigegeben. Falls Threads warten, erhält
einer von ihnen den Lock (welcher ist nicht festgelegt).
PPS 2.1-34
Beispiel: Monitor
public class Konto {
int kontostand = 0;
synchronized void einzahlen(int betrag) {kontostand+=betrag; }
synchronized void abheben(int betrag) {kontostand-=betrag; }
}
public class Kontoinhaber extends Thread {
public void run() { einzahlen(200); abheben(50); }
}
public class Bsp {
Konto unserKonto = new Konto();
Kontoinhaber susi = new Kontoinhaber(unserKonto);
Kontoinhaber fritz = new Kontoinhaber(unserKonto);
susi.start(); fritz.start();
}
PPS 2.1-35
Parallelität und Serialisierung
Java Threads werden gegenwärtig meist pseudoparallel
ausgeführt ("green threads")
Parallelausführung ist möglich falls
der Rechner mehrere Prozessoren enthält und
die Java-Implementierung die Parallelausführung
unterstützt ("native threads")
Serialisierung = durch Warten auf Lock bedingte
sequentielle Ausführung der Threads
Unnötige Serialisierung vermeiden (auch bei pseudokritische Abschnitte kurz halten
paralleler Ausführung)->
PPS 2.1-36
wait und notify
Weiterer Synchronisationsmechanismus - eignet sich für
Synchronisation zwischen Produzenten und
Konsumenten (Anwendung Monitor: ausschließlicher Zugriff)
Durch Aufruf wait() gibt der Besitzer des Locks diesen
freiwillig ab und begibt sich in einen zweiten Warteraum
("Schlafsaal") zum Objekt
wait() kann nur in kritischem Bereich aufgerufen werden
Durch Aufruf von notify() wird ein (willkürlich
ausgewählter) Thread des Schlafsaals in den Warteraum
des Locks geschickt
Nutzen wait/notify: Vermeidung aktiven Wartens
PPS 2.1-37
Anwendung von wait /notify
Konsument
Produzent
Konsument
Konsument
Lager
Alle Zugriffe geschützt
durch synchronized
nach Produktion
einer Einheit:
notify();
if (Lager leer)
wait();
PPS 2.1-38
Thread Scheduling
Threads können sich in 4 Zuständen befinden
aktiv - in Ausführung, d.h. läuft auf Prozessor
rechenbereit - wartet auf Zuweisung eines Prozessors
wartend - wartet auf Lock oder notify()
beendet
Algorithmus zur Prozessorzuordnung (Scheduling) ist
implementierungsabhängig -> Programme sollten in
jedem Fall korrekt laufen
meist: Zeitscheiben, Prioritäten
Programmierer kann Scheduling beeinflussen, z.B. durch
Setzen von Prioritäten
PPS 2.1-39
2.3. Applets
Java-Programme, deren Ausführung typischerweise von
einem Web-Browser gesteuert wird
Statt main() ruft der Browser situationsabhängig (eventuell
überschriebene) Methoden der Klasse Applet auf: init(),
start(), stop() und andere
Als mobiler Code unterliegen Applets sicherheitsbedingten
Einschränkungen, z.B. Verbot des Zugriffs auf Files
Ausnahme: signierte Applets
Bytecode-Verifizierer überprüft nach dem Laden
sicherheitsrelevante Eigenschaften des Codes
zum Applet gehörige Klassen werden nach Bedarf geladen
Alternative: jar-Archiv
Applet-Programmierung ist grafik- und ereignisorientiert
PPS 2.1-40
Beispiel: Applets
import java.applet.*;
import java.awt.*;
public class Bsp extends Applet {
public void paint(Graphics g) {
g.drawString("Hello World",10, 20);
g.drawLine(10,22,80,22);
}
}
<html>
<body>
<applet code="Bsp.class" width=300 height=200>
</applet>
</body>
</html>
PPS 2.1-41
2.4. Remote Method Invocation
auch: entfernter Methodenaufruf, RMI
objektorientiertes Konzept zur Realisierung des
Client/Server-Paradigmas
Kennzeichen:
Nachrichtenaustausch über Rechnergrenzen
hinweg
Objekte verbleiben auf ihrem Rechner
RMI kann durch Code-Mobilität ergänzt werden;
diese ist jedoch nicht Bestandteil des Konzepts
PPS 2.1-42
Funktionsweise RMI
Client
Server
Stub
Skeleton
Netzwerkverbindung
Client = Prozeß, der aufrufendes Objekt ausführt
Server = Prozeß, der dienstanbietendes Objekt ausführt
PPS 2.1-43
Stub und Skeleton
Stub: lokale Methode auf Client-Seite, wird vom
Client stellvertretend für die entfernte Methode
aufgerufen
Skeleton analog, aber auf Server-Seite
Stub und Skeleton werden mit Hilfe eines
Werkzeugs erzeugt
Stub und Skeleton enthalten Programmcode zur
Realisierung der Kommunikation -> ist transparent
für das Anwendungsprogramm
PPS 2.1-44
Datenübertragung
Zulässige Parameter:
(1) Werte primitiver Typen
(2) serialisierbare Objekte
(3) Verweise auf RMI-Objekte
Stub/Skeleton packen/entpacken Parameter und
Ergebnis
erfolgt bei (2) mittels Serialisierung
PPS 2.1-45
Serialisierung
Abspeichern des Objektzustandes in einem zur
Datenübertragung geeigneten Format (Folge von Bits)
Abgespeichert werden
die Werte aller eigenen und geerbten Attribute, außer
static, transient
für Attribute, die Objekte sind, rekursiv auch deren
Attribute (bei zyklischen Verweisen nur einmal)
Verweis auf zugehörige Klasse (Programmtext, Version)
Objekte können nur serialisiert werden, wenn sie das
(leere) Interface Serializable implementieren
Weitere Anwendung: Sichern in Files (Persistenz)
PPS 2.1-46
Praktische Umsetzung mit Java RMI
1) Definition eines Remote Interface für die Serverklasse
Unterklasse von java.rmi.Remote
jede Methode muß throws RemoteException deklarieren
2) Erstellen einer Klasse A, die das Interface implementiert
3) Erzeugen von Stub und Skeleton mit Hilfe des Werkzeugs
rmic
4) Starten der RMI-Registry als Hintergrundprozeß auf
dem Server-Rechner
5) Starten des Serverprozesses - darin Erzeugen eines
Objekts der Klasse A und Anmelden dieses Objekts unter
einem Namen xyz bei der RMI-Registry (mittels Naming.bind)
Serverprozeß läuft auch nach Beendigung von main() weiter
PPS 2.1-47
Praktische Umsetzung 2
6) Kopieren des Stub auf den Client-Rechner (ins
Arbeitsverzeichnis)
7) Client-Programm muß kennen:
Name des Zielrechners (z.B. paral.informatik.uni-leipzig.de)
frei gewählten Namen des Servers (d.h.: xyz)
Erhält dann durch Aufruf von Naming.lookup(daten)
vom RMI Registry des Server-Rechners einen Verweis
fernesObjekt auf das Server-Objekt
8) Dieser Verweis ermöglicht Aufruf von Server-Methoden
mit der üblichen Syntax, z.B. fernesObjekt.m()
PPS 2.1-48
3. Skriptsprachen
Literatur für dieses Kapitel:
D. Barron: The World of Scripting Languages, Wiley, 2000.
PPS 3-1
Merkmale
werden häufig nicht zu den Programmiersprachen gezählt
einfache Sprachen
leicht zu erlernen (zumindest Sprachkonzept)
schnelle Entwicklung von Programmen
pragmatisch
einfaches Typsystem, dynamische Typisierung
werden interpretiert oder implizit kompiliert
-> direkter Aufruf des Programms ohne vorherige
Übersetzung
große praktische Bedeutung
PPS 3-2
Anwendungsgebiete und Sprachen
Systemadministration , Steuerung von Anwendungen
Betriebssysteme, Netzwerke, Datenbanken
Unix Shells, Perl, Tcl
Zusammensetzen von Komponenten
Tk, Visual Basic
Anwendungen, bei denen schnelle Programmentwicklung
wichtiger ist als schnelle Programmausführung (Prototyp)
Visual Basic
Web-Programmierung auf Client- und Serverseite
JavaScript, VBScript, Perl
=>Skriptsprachen sind auf ein (eventuell breites)
Anwendungsgebiet spezialisiert
PPS 3-3
Perl - Einführung
Perl = Practical Extraction and Report Language
Ende 80-er Jahre eingeführt, danach weiterentwickelt
zunächst Unix, jetzt alle wichtigen Betriebssysteme
Spezialisierung: Textverarbeitung, Extraktion von
Informationen aus Files
Befehle des Betriebssystems (auch zur Netzwerkprogrammierung) sind in Perl-Skripts direkt verfügbar
Syntax erlaubt Varianten des gleichen Befehls - Prinzip:
fehlende Informationen werden sinnvoll ergänzt
Beispiel: Variablen können, müssen aber nicht deklariert werden
günstig für ungeübten Programmierer
PPS 3-4
Beispiele: Perl
Schreiben in File Bsp.pl:
#!/usr/bin/perl
print "Hello World\n"
#!/usr/bin/perl
while (<STDIN>) {
print if /wichtig/
};
Ausführung in Unix
durch:
>Bsp
Ausführung in Windows
durch:
> perl Bsp
#!/usr/bin/perl
$word = shift;
while (<>) {print if /$word/};
Aufruf durch:
Bsp xyz File1 File2
PPS 3-5
Datentypen in Perl
Typ von Variablen wird im Bezeichner kodiert:
Skalare Daten: $name
Arrays: @name
Hashes: %name
Funktionen: &name
Skalare Datentypen: String, Zahl
Dynamisch-typisierte Sprache: System kennt den
aktuellen Typ der Variablen und konvertiert wo nötig
Operatoren: arithmetisch, logisch, bitweise, Vergleich,
bedingter Ausdruck, Zeichenreihen
z.B. $a = "Hallo" x 3;
$b = "Ein $a";
$b .= $a;
++$a;
PPS 3-6
Zusammengesetzte Datentypen
Liste
z.B. ("rot", "blau", "gruen"),
qw(rot blau gruen),
(1..8)
Vertauschen von Daten: ($a, $b) = ($b, $a);
Array
z.B. @bsp = (0, "nichts", 0.0);
-> $bsp[0] enthält 0 etc.
Zuweisung der Feldlänge: $laenge = @bsp;
Hash = inhaltsadressiertes Feld, assoziatives Feld
z.B. $myHash{baum} = "tree"; ...
%myHash = (baum => "tree", apfel => apple, ...);
Liste der Schlüssel/Werte: keys %myHash; values %myHash;
PPS 3-7
Steuerstruktur
Blöcke
bedingte Anweisungen
if ($n>20) {
print "gross"
} else {
print "klein"
}
print "gross" if (n>20);
print "klein" unless (n>20);
Schleifen
z.B. $a += 2 while $a < $b;
$a += 2 until $a > $b;
foreach $i reverse (1..10) { print $i };
for ($i=1; $i<10; $i++) { print $i };
auch: Objekte, Pakete etc.
PPS 3-8
Reguläre Ausdrücke
Beschreiben Muster in Zeichenreihen unter Verwendung
von Symbolen:
^ - Zeilenanfang, $ - Zeilenende
. - beliebiges Zeichen
[] - Zeichen aus Liste, z.B. /[aeiou]/
- - abgekürzte Aufzählung, z.B. /[0..9]/
[^]- Zeichen außer angegebenen, z.B. /^[ou]/
*, +, ?- Wiederholung (* für >=0, + für >=1, ? für 0,1)
| - Alternative, z.B. /From: | To:/
()- Gruppenbildung
{n,m}- gezählte Wiederholung, z.B. /([0..9]{1,3}\.){3}/
und andere
PPS 3-9
4. Maschinennahe
Programmierung
Literatur für dieses Kapitel:
H.-P. Gumm, M. Sommer: Einführung in die Informatik,
Oldenbourg-Verlag, 2000, Abschnitte 5.4-5.6
PPS 4-1
Was ist Assembler
Abstraktionsebene oberhalb von Maschinenbefehlen
Beispiel: MOV DX, 0
vs.
101110100000000000000000
Maschinenbefehle sind eventuell durch Folge von
Mikrobefehlen realisiert
Zwei Bedeutungen des Begriffs:
Sprache, die Maschinenbefehle verständlich kodiert und
einfache Möglichkeiten zur Programmstrukturierung
bereitstellt
Programm, das Assemblerprogramme in
Maschinenprogramme umwandelt
Informationen zu konkreten Assemblersprachen findet
man z.B. in der Dokumentation des jeweiligen Prozessors
PPS 4-2
Bedeutung Assembler
Wozu beschäftigen wir uns mit Assembler?
Zielsprache im Compilerbau
Verständnis für Performance von Programmen
Zusammenspiel Programmierer - Compiler
in sehr seltenen Ausnahmefällen Performance-kritische
Programmabschnitte in Assembler schreiben
Programmierung von Basisfunktionen des
Betriebssystems (Zugriff auf periphere Geräte)
Geschichte von Programmiersprachen
Wozu nicht?
Programmierung von Anwendungsprogrammen
PPS 4-3
Eigenschaften von Assembler
Maschinenabhängig -> Assemblerprogramme sind nicht
portabel
evtl. Abwärtskompatibilität innerhalb einer Prozessorfamilie
betrachten hier typische und grundlegende Befehlsklassen
Assemblersprachen sind minimalistisch
enthalten (fast) nur die vom Prozessor unterstützten Grundbefehle
Komplexere Operationen müssen im Programm aus Grundbefehlen
zusammengesetzt werden
Verwendung Assembler:
Assembler als Teil des Compilers, z.B. gcc -S myprog.c, gcc myprog.s
Assembler als eigenständiges Programm
Einfügen von Assemblercode in Hochsprachprogramme
PPS 4-4
Rechnermodell
betrachten von-Neumann Rechner
Speicher unterteilt in Register und (Haupt-)speicher
unterscheiden
Mehrzweckregister R1, R2,...
Spezialregister, z.B. Programmzähler PC, Stackzeiger SP
Statusregister (FLAGS)
Registerbreite architekturabhängig, z.B. 4 Byte
Operationen verlangen evtl. bestimmtes Register
fassen Speicher als Array der Länge MAX_ADDRESS auf,
mit Indizes = Adressen
Speicher enthält (in verschiedenen Segmenten)
Programmtext und Daten des Programms
PPS 4-5
Speicherzugriff und Adressierung
bei RISC-Architekturen können nur explizite Lese- und
Schreibbefehle auf den Speicher zugreifen
arithmetische Operationen erwarten die Operanden in
Registern
Adressierungsarten:
Direktoperand, z.B. MOV R1,14
Registerzugriff, z.B. MOV R1, R2
direkte Adressierung, z.B. MOV R1, [12]
indizierte Addressierung, z.B. MOV R1, R2[R3]
indirekte Adressierung, z.B. MOV R1, (R2)
PPS 4-6
Datentypen
unterscheiden
Byte = 8 Bit, Wort = 16 Bit, Doppelwort = 32 Bit u.a.
Bitfolgen werden von verschiedenen Operationen als int
mit/ohne Vorzeichen, float etc. interpretiert
betrachten byteadressierten Speicher (z.B. Intel Pentium):
3AH
4H
Wort auf 1H enthält 12E2H
BCH
3H
12H
2H
Doppelwort auf 0H enthält
BC12E201H
E2H
1H
Byte auf 4H enthält 3AH
01H
0H
für effizienten Zugriff müssen Daten korrekt ausgerichtet
sein, z.B. Doppelwort an durch 4 teilbarer Byteadresse
PPS 4-7
Adreßformen
unterscheiden
Einadreßform: op Quelle
Zweiadreßform: Ziel = Ziel op Quelle,
Dreiadreßform: Ziel = Quelle1 op Quelle2
Beispiel zur Zweiadreßform: Berechnung von a=(a+b)-(7-c)
MOV R1, a
MOV R2, b
ADD R1, R2
MOV R3, 7
MOV R4, c
SUB R3, R4
SUB R1, R3
MOV a, R1
PPS 4-8
Flags
Flag = einzelnes Bit des Registers FLAGS
unterscheiden Status-, Steuer- und Systemflags
Statusflags werden automatisch durch die ALU gesetzt
und enthalten Informationen zur letzten Operation
welche Flags aktualisiert werden, hängt von der konkreten
Operation ab
Beispiele:
Z (Zero) - Ergebnis der letzten Operation war 0
C (Carry) - Überlauf bei vorzeichenlosen ganzen Zahlen
O (Overflow) - Überlauf bei ganzen Zahlen mit Vorzeichen
S (Sign) - Ergebnis war negativ
PPS 4-9
Beispiel: Flags
(im Intel Pentium sind AL , BL Register der Breite 1 Byte)
MOV AL, -3
MOV BL, -1
ADD AL, BL
AL
FDH
AL
FCH
Ergebnis = -4
Gültig, da O=0
MOV AL, 253
MOV BL, 255
ADD AL, BL
BL
FFH
FLAGS
1
C
0
O
Ergebnis = 252
Ungültig, da C=1
PPS 4-10
Operationen
Arithmetische Operationen: ADD, SUB, MUL, DIV
Register für Produkt bzw. Dividend müssen doppelte Breite haben
Beispiel Intel Pentium:
MOV AL, 17
MOV DL, 30
MUL DL ; AX := AL * DL
Vergleiche: CMP
Logische Operationen: AND, OR, XOR, NOT
können für Bitoperationen verwendet werden, z.B. OR AL, 0100 0010B
Schiebebefehle, z.B. SHR AL, 1
Anwendung: Multiplikation, Division mit Zweierpotenzen
Bit- und Byteoperationen, u.a.
PPS 4-11
Sprungbefehle
bewirken Laden des Programmzählers mit neuem Wert
unterscheiden unbedingte und bedingte Sprünge
Beispiel: Berechnung von AX = 1+2+ ... +CX
MOV AX, 0
nochmal: CMP CX, 0
JZ ende
; bedingter Sprung (Jump on Zero)
ADD AX, CX
DEC CX
JMP nochmal ; unbedingter Sprung
ende: ...
bedingte Sprünge beziehen sich auf Flags der vorigen
Operation; existiert Vielzahl bedingter Sprungbefehle
PPS 4-12
Speichersegmente
Speicher ist unterteilt in Daten-, Code- und
Stacksegment
Segmente sind verschiebbar, aktuelle Startadressen der
Segmente stehen in Spezialregistern DS, CS, SS
bei Datenzugriffen gilt:
physische Adresse = 16 * DS + angegebene Adresse
beim Laden von Befehlen gilt:
Adresse nächster Befehl = 16 * CS + PC
Segmente können sich überlappen
Größe/Überlappung der Segmente kann im Programm
festgelegt werden, z.B. . stack 100H
PPS 4-13
Symbolische Adressen
(im Codesegment: Sprungmarken)
im Datensegment: symbolische Datenadressen
werden am Anfang des Assemblerprogramms deklariert
und eventuell initialisiert
können später statt expliziter Adressen verwendet
werden
DB = Define Byte, DW = Define Word
Beispiel: Alter DB 0
Name DB 15 DUP(0)
Groesse DW ?
Effekt: Es wird Speicherplatz reserviert, z.B.
Alter: DS:04, Name: DS:05 ... DS:0E, Groesse: DS:0F und DS:10
PPS 4-14
Unterprogramme
meineFunktion: Befehl 1
...
Befehl n
RET
main: ...
CALL meineFunktion
...
END main
Prozedurdeklaration
Prozeduraufruf
Es dürfen beliebig viele Unterprogramme deklariert
werden
Rekursive Aufrufe sind zulässig
Hauptprogramm ist durch ´END´ gekennzeichnet
PPS 4-15
Verwendung des Stack
Stack = durch SS adressiertes Segment des Speichers
Zugriff erfolgt mittels PUSH, POP
wird für Implementierung von Unterprogrammaufrufen
verwendet, insbesondere Parameterübergabe
CALL meineFunktion bewirkt
PUSH PC
; alten Programmzähler sichern
JMP meineFunktion ; unbedingter Sprung
RET bewirkt
POP PC ; wieder alten Programmzähler laden
innerhalb des Unterprogramms benötigte Register sollten zu
Beginn gerettet und am Ende wiederhergestellt werden
PPS 4-16
Parameterübergabe
Übergabe in Registern
welche Register, ist Konvention zwischen Aufrufer und
aufgerufenem Unterprogramm
geeignet für wenige / kurze Parameter
Übergabe auf Stack
Übergabe mittels PUSH
Entfernen mittels RET k (k Byte entfernen, RET)
Zugriff über Spezialregister SP (Stack Pointer) und BP
(Base Pointer)
z.B. MOV BP, SP
MOV AX, [BP+4]
PPS 4-17
Parameterübergabe auf Stack
SS
Lokale
Variablen des
Aufrufers
Datenrahmen des
Unterprogramms
(Frame)
Übergebene
Parameter
PC
BP
Lokale Variable
Stack wächst hier nach unten:
SP
PUSH
POP
PPS 4-18
5. Zusammenfassender Überblick
Unterscheiden vier grundlegende Paradigmen:
Imperative Programmierung
Objektorientierte Programmierung
Funktionale Programmierung
Logikprogrammierung
Weitere Sprachklassen:
Parallele, verteilte, nebenläufige Programmierung
Skriptsprachen
Maschinennahe Programmierung
PPS 5-1
Herunterladen