Mein Vortrag gliedert sich in 3 Teile. Ich werde etwas
erzählen über Applets & Applikationen (Fortsetzung von Mirko),
Komponenten in Java, die dazugehörigen Layout-Manager und Multithreading.
Wie vorher schon erwähnt gibt es in Java zwei Arten von Programmen : Applets und Applikationen.
Bekannter sind sicherlich Applets, die in HTML Seiten eingebunden werden können, um dadurch daß Internet, das WWW im Speziellen, dynamischer machen.
Applikationen sind "Stand-alone-Anwendungen", wie sie auch von anderen Programmiersprachen bekannt sind.
Es ist möglich Programme zu schreiben, die als Applet und als Applikation lauffähig sind.
Fange ich nun mit Applikationen an :
Bei einer Applikation muß die Methode "public static void main(String args[])" implementiert sein. Beim Start einer Applikation wird zuerst diese Methode aufgerufen.
. . .
Hier wird z.B. beim Programmstart ein Frame definiert und darin ein Panel (ein sogenannter "Container"). Das Programm, welches in diesem Fenster ablaufen soll, wird dann in der Klasse "CPanel" ausgeführt. Soweit am Anfang dazu, wie das Programm genau aussieht, werde ich gleich zeigen.
Applets werden in der Regel innerhalb eines Browsers ausgeführt. Bekannteste Vertreter sind der Netscape Navigator ab Version 2 und der Internet Explorer ab Version 3. Bei der Programmentwicklung geht dies auch im AppletViewer, der z.b. im JDK von SUN mitgeliefert wird.
Applets werden über das "<APPLET" Tag im HTML Code eingebunden. Ich habe hier mal ein Beispiel :
...
Daran kan ich auch gleich die Attribute erklären :
CODE : Gibt Datei der Hauptklasse an, muß im Verzeichnis
der HTML Datei liegen
WIDTH : Breite in Pixel
HEIGHT : Höhe in Pixel
Folgende Attribute sind optional :
CODEBASE : Anderes Verzeichnis, falls sich die Datei nicht
im selben Verzeichnis wie die HTML Datei befindet
ALIGN : Wie das Applet auf der Seite ausgerichtet sein
soll (z.B. "right", "left", "top" usw.)
ALT : Alternativer Text, bei Browsern, die kein Java
können
NAME : Name des Applets, wenn mehrer applets auf einer
Seite miteinander kommunizieren
(VSPACE) : nur bei Align = right odert Align=left, Abstand
in vertikaler Richtung um das Applet
(HSPACE) : nur bei Align = right odert Align=left, Abstand
in horinzontaler Richtung um das Applet
<PARAM>Tag : Übergabeparameter
(NAME) : Logischer Name des Übergabeparameters
(VALUE) : Eigentlicher Wert des Übergabeparameters
(String)
Es gibt 4 Methoden, mit dem man den Lebenszyklus eines Applets steuern kann :
- init() : Wird nach dem nach dem Laden des Applets ausgeführt,
also ist dies die Initialisierung.
- start() : Wird nach init() ausgeführt. Wird auch
beim wiederholten Laden einer Seite aufgerufen.
- stop() : Das Gegenstück zu start(). Wird also
z.B. ausgeführt wenn die Seite im Browser verlassen wird.
- destroy() : Wird aufgerufen, wenn das Applet zerstört
wird. Netscape hilft hier automatisch nach, indem bei übermäßiger
Speicherbelastung alle überflüssigen Applets zerstört werden.
Beim erneuten Laden wird der Initialisierungsvorgang erneut gestartet.
Applets unterliegen bestimmten Sicherheitsrestriktionen,
die vom sogenannten Security Manager überwacht werden.Damit sollen
Dateizugriffe oder sonstige böswillige Aktionen verhindert werden.
Bei Applikationen gibt es sowas nicht. Die haben, wie
jedes andere Programm auch, vollen Dateizugriff.
Hier noch ein kurzes Beispiel für die Initialisierung eines Applets:
. . .
Da ein Applet standardmäßig schon immer in
einem Frame ausgeführt wird, braucht hier nur ein Panel definiert
werden. Auch hier wird das Programm in der Klasse "CPanel" weitergeführt,
womit der Code in der Klasse "CPanel" dann als Applet und Applikation lauffähig
ist.
Als Ganzes sieht das Programm dann folgendermaßen
aus :
. . .Als Applet sieht das Hallo Welt dann so aus :
. . .
- Die Methode public static void main wird ausgeführt
wenn es als Applikation gestartet wird
- Die Methode public void init() wird ausgeführt
wenn es als Applet gestartet wird
- In der Klasse CPanel steht der ProgrammCode
. . .
Als Applet sieht das dann so aus :
Und als Applikation muß ich den Browser nun wohl verlassen ...
Eine graphische Benutzeroberfläche besteht aus 2
Schritten
- Eine Benutzeroberfläche erstellen
- Aktionen implementieren (hat Mirko erklärt ->
Event Handling)
Java stellt das "AWT", das Abstraction Window Toolkit,
zur Verfügung. Abstrakt deshalb, weil der Benutzer sich keine Gedanken
darüber zu machen braucht, wie die Komponenten für ein betsimmtes
System umgesetzt werden. Es beeinhaltet vordefinierte Komponenten, mit
denen man eine graphische Oberfläche erstellen kann.
Es ist relativ einfach gehalten, aber dafür ist
es einfacher im Aufbau und unabhängiger vom Betriebssystem.
Um Komponenten zu plazieren und anzuzeigen benötigt man einen Container, z.B. ein Panel. Ich gehe davon aus, daß schon ein Container vorhanden ist, auf dem dann Komponenten plaziert werden können.
Folgende Komponenten stellt Java zur Verfuegung (wer Delphi schonmal programmiert hat oder eine andere graphische Oberfläche, dem kommt dies bekannt vor):
Hier sind die meisten alle dargestellt, in einem extra Fenster, weil in der vorherigen Version kein Menues dargestellt werden können. Deswegen benutzt man auch Frames für Applets, die Menues benötigen.
- Panel/Frames/Window : Container für Komponenten
notwendig.
- Menu/MenuItem/MenuBar: Menueleiste, Untermenues und
Markieren von Einträgen
- Checkbox, CheckboxGroup(Radiobuttons) : Dienen dazu
eine Auswahlmöglichkeit anzuzeigen. Aus Groups kann immer nur eine
aktiv sein.
- Listbox : Man kann die Anzahl der Einträge festlegen
und ob Mehrfachauswahl möglich ist.
- Choice : Dient zur Darstellung eines Pop-Up Menues
- Buttons : Hier zu beachten ist, daß er relativ
wenig Eigenschaften enthält,und daß das Aussehen von der verwendeten
Oberfläche abhängt.
- Label : Eine Anzeige von einem einzeiligen Text. Rechtsbündig,
linksbündig und Zentrierte Anzeigen sind möglich.
- TextField, TextArea : Ermöglichen Eingabe, Bearbeiten
und Selektieren von Text. Man kann sie auch auf nicht editierbar setzen.
- Scrollbar : Kann verwendet um einen für den Bildschirm
zu großen Bildbereich zugänglich zu machen oder einen Regler
zu implementieren.Auf die Bewegung des Regelers kann mit Code reagiert
werden.
- Canvas (nicht dargestellt): Wird dazu benutzt Grafiken,
ob selbst erzeugt oder in Form von Bildern, darzustellen. Werde ich hier
nicht weiter darstellen.
- Dialog/Filedialog (nicht dargestellt) : Filedialog : Klasse, die
einen Dialog zum Auswählen von Dateien darstellt (Öffnen/Speichern),
Fehlermeldungen z.B. können in einem normalen Dialogfenster dargestellt
werden, erkläre ich hier nicht weiter
Hier noch einmal der Quelltext für dieses kleine Programm. Wie man sehen kann, kann es ohne visuelle Programmierung, wie es z.B. in Delphi möglich ist, recht umfangreich werden.
Layout-Manager
Warum gibt es in Java Layou-Manager?
- Flexibler. Absolute Angaben machen mehr Arbeit beim Einfügen
weiterer Komponenten, beim Verstellen der Fenstergröße und der
Auflösung.
- Da hier nur relative Angaben gemacht werden, braucht der Programmierer
sich keine Sorgen um die Darstellung zu machen.
Welche?
- FlowLayout : Ist der voreingestellte Layout-Manager von Panels. Das
ist das Beispiel von eben, weil da schon dieser Layout-Manager verwendet
wurde. Hier werden alle Komponenten einfach alle in einer Reihe angeordnet.
Wenn der Container zu schmal wird, werden einfach mehrere Zeilen dargestellt.
Die Komponenten werden Links- , rechtsbündig oder zentriert dargestellt,
in diesem Fall zentriert.
Wie man hier auch sehen kann, werden beim Verstellen der Fenstergröße alle Kompoenten neu anhand des verwendeten Layout-Mangaers dargestellt.
- BorderLayout : Voreingestellt für die Container Window, Frame,
Dialog. Bis zu 5 Komponenten können verwaltet werden, die Rechts,
Links, Unten, Oben und in der Mitte plaziert werden, welches Java mit den
Begriffen "North","South","West","East" und "Center" mitgeteilt wird..
- CardLayout : Die Komponenten werden wie ein Stapel Spielkarten angeordnet,
nur die oberste ist sichtbar. Man könnte z.B. die einzelnen Bilder
einer Animation damit anzeigen. Da dies etwas komplexer ist, lasse ich
das hier weg.
- GridLayout : Hier werde die Komponenten in einem Gitter mit gleich
großen Zellen angeordnet. In einer Gitterzelle kann genau eine Komponente
angeordnet werden. Die Gitterzellen werden von oben links beginnend zeilenweise
mit "aufgefüllt".
- GridBagLayout : Hier basiert die Darstellung auch auf einem Gitter.
Nur durch folgende Eigenschaften ist die Darstellung erheblich flexibler
:
- - Einen Komponente kann über mehrer Zellen gehen
- - Spalten und Zeilen könne unterschiedlich hoch/breit sein
- - Die Komponent muß die Gitterzelle nicht unbedingt voll ausfüllen
- - - auch die ist etwas komplexer, da es viele Eigenschaften, bzw.
Elemente, gibt, die eingestellt werden müssen.
- Nicht unerwähnt wollte ich lassen, das es durchaus möglich
ist, selbstdefinierte Layout-Manager zu erstellen. Grundsätzlich sollte
man sich dies jedoch gründlich überlegen, da vordefinerte Methoden
überschrieben werden müssen.
- Außerdem ist auch noch möglich, Komponenten ohne einen
Layout-Manager zu plazieren. Z.B. kann man sie einfach untereinander plazieren,
oder sogar absolute Positionen angeben, mit den Nachteilen, die ich am
Anfang erwähnt hatte.
- Damit komplexere Oberflächen gestaltet werden können, ist
es notwendig, daß Layout-Manager ineinander verschachtelt werden.
Bei einem einfachen Beispiel, sieht das z.B. so aus :
- - Die Komponenten sind mit dem BorderLayout plaziert : "North", "South"
und "Center". In South habe ich ein eigenes "Panel" definiert, wo die Komponenten
mit dem Flow-Layout Manager angeordnet sind.
Java ist eine Multithreading fähige Programmiersprache. Es ist also möglich parallelablaufende Programmteile zu schreiben, die alle in einem eigenem Proeß ausgeführt werden.
Ein Thread ist also ein eigener Prozeß, um so ein Teilprogram abzuarbeiten.
Die Perfomance eines Programms kann so evtl. getseigert werden. Bei einem Ein-Prozessorsystem ist natürlich keine echte Paralleltität möglich, aber durch das schnelle Umschalten und durch das "Schlafengehen" eines Threads wird durch Java der Eindruck von Parallelität erzeugt.
Um die Multithreadingfähigkeiten von Java zu demonstrieren und visualisieren werde ich ein Programm mit 5 unterschiedlich "schnellen" Threads vorstellen.
Erstmal erkläre ich die zwei verschiedene Möglichkeiten, die es in Java gibt, Threads zu erzeugen :
1) Man implementiert die Schablone Runnable.
- Also man schreibt hinter die Klassendefinition "implements Runnable"
- In der Run() Methode steht der ProgrammCode des Threads (wird durch
start aufgerufen)
- Nach der Instantiierung und dem Aufrufen der Methode start() wird
der Thread gestartet.
Zu beachten ist noch, daß dieser Thread alle 100ms einmal ausgeführt wird, weil er mit "sleep(100)" immer 100ms eine Pause macht.
- Und hier noch das kleine Beispiel ... : Eine kleine Laufschrift, die alle 100ms aufgerufen wird
2) Das Ableiten der Thread Klasse ist die 2. Möglichkeit um einen Thread zu definieren.
Dazu erbt die Klasse mit "extends Thread" die Threadeigenschaften bzw. Methoden.
Ich habe das in diesem Beispiel so gemacht, daß die 4 einzelnen Threads im Konstruktor definiert, instantiiert und gestartet werden.
Die einzelnen Threads selber sind wieder von dieser Klasse abgeleitet ("extends Akt_Main"),wobei sie dessen Eigenschaften erben, also auch die Threadmethoden, und dort wird in der Methode "public void run()" der ProgrammCode des Threads implementiert. Hier wird der Thread jede Sekunde ausgeführt.
Auch hier noch das komplette Beispiel. Wie man sehen kann laufen hier 5 unabhängige Threads, die alle in unterschiedlichen Intervallen aufgerufen werden. DasWechseln der farbe Blau und Weiß demosntriert, das die 4 Threads alle in unterschiedlichen Intervallen aufgerufen werden. Da wird dann immer das Ausgabefeld aktualisiert, von 1er bis alle 4 Sekunden. Und unten ist noch die bekannte Lufschrift als 5. Thread. Den kompletten Quelltext will ich euch jetzt nicht antun...
-----
Ein Thread kann vier Zustämde annehmen:
- Neu : Nachdem der Thread mit "new" angelegt wurde befindet er sich
im Zustand Neu. Es dürfen nur die Methoden start() und stop() angewendet
werden.
- Bereit : Nachdem er mit start() gestartet wurde, befindet er sich
in Bereit
- Blockiert : Wenn die Abarbeitung unterbrochen wurde, befindet er
sich im Zustand Blockiert
- Fertig : Wenn er abgearbeitet wurde oder wenn er durch stop() beendet
wurde ist der Thread im Zustand Fertig..
- Wie eben schon gesagt, kann der Zustand Neu nur durch die Methoden start() und stop() geändert werden.
Die Blockiert Methoden will ich nur kurz Ansprechen :
- yield : Veranlaßt den Thread verbleibende Prozessorzeit abzugeben
- sleep : Legt den Thread für eine bestimmte Zeit "schlafen"
- join() : Wartet auf das Ende eines anderen Thread (Vater/Kind...)
- Suspend()/Resume() : Unterbrechung des Threads, also eine Art Pause
- wait()/Notify() : Kann nur in Synchronisierten Methoden verwendet
werden (erkläre ich gleich).Mit wait() wird der Thread veranlaßt
so lange zu warten, bis ihm durch notify() mittgeteilt wird, daß
ds gesperrte Objekt für ihn wieder freigegeben wurde (werde ich gleich
demonstrieren). Also können einzelne Objekte damit für den Zugriff
geperrt werden.
Bei der Bearbeitung von Threads können Inkonsistenzen auftreten.
- Ich werde das mal an einem kleinen Beispiel demonstrieren : das Parkplatzproblem
Wir stellen uns einen Parkplatz vor, wo ein Auto zehnmal geparkt ("Eingetragen") und wieder abgeholt werden soll in zufälligen Abständen. Dazu werden in diesem Programm 2 UNABHÄNGIGE Threads benutzt, die nach einer zufälligen Zeit jeweils zehnmal "Parken" und "Abholen". Wie wir sehen funktioniert das noch nicht nicht so. Bei jedem neuen Start kommt ein anderes Ergenis raus.
Deswegen gibt es z.B. die Methoden wait() und notify(), die dem Programmierer eine größere Kontrolle über die Abläufe gibt. Dies geht nur im Zusammenhang mit den sogenannten Monitoren. Dafür wird der Modifier Synchronized eingeführt, der verhindert, das auf Ressourcen gleichzeitig zugegriffen werden kann.
- Am Beispiel sehen wir, das die Methoden "Parken" und "Abholen mit
dem Schlüsselwort "synchronized" versehen sind.
Das bedeutet, daß dies nicht gleichzeitig geschehen kann.
Zudem werden die Methoden wait() und notify() dazu verwendet, daß
das Abholen nicht ohne einen Parkvorgang erledigt werden kann. Also z.b:
bei der Methode parken() wird wait() aufgerufen, wenn schon ein Auto geparkt
worden ist. Dieser Thread wird erst wieder freigegeben, wenn in der Methode
abholen() notify() aufgerufen wird (und umgekehrt).
Wie wir am Programm sehen, funktioniert das Parken und Abholen nun in der richtigen Reihenfolge.
Ende