Einleitung

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.
 

Applets & Applikationen

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 ...

Komponenten & Layout-Manager
 

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.

 
Multithreading in Java
 

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