schonmal über einen Proxy nachgedacht… ?
Proxy??
java.lang.reflect.Proxy, für die Zwecke braucht man das aber nicht.
Die Threads sind zur Visualierung von Sortieralgorithmen da, dem Benutzer soll eine parallele Ausführung :dieser angezeigt werden. Diese sollen aber nicht nur selbständig ablaufen, sondern auch schrittweise vom :Benutzer gesteuert werden.
Also 2 Varinaten: einmal stop&Go und einmal „durchlaufen bis zum ende“
Im Prinzip will ich das Objektarray durchgehen, und jedem Thread sagen, er möge bis zum nächsten Haltepunkt :weiterzumachen, dann können die Werte aus dem Objektarray ausgelesen werden und irgendwie dargestellt werden.
Ohne dir auf die Füsse tretten zu wollen: du hast nocht nicht viel mit Threads gearbeitet, oder ? Der AWT-thread sagt dir auch nix ? Es ist eine Hausaufgabe ? 3x ja ?
OK, ich hol jetzt weiter etwas aus und beschreibt eine komplexere und „korrektere“ Lösung,… da es eine Hausaufgabe ist werd ich dir aber keine Komplett-lösung hinschreiben.
Du willst Threads starten die was berrechen und später die Werte zusammensuchen und darstellen. Die Quiz-Frage ist: welcher Thread sammelt die Werte ein und wie weiss er wann die anderen fertig sind ?
Das mit dem „auf’s-fertg-werden-warten“ ist einfach, dafür gibts Object.wait() (und notifyAll()). ABER:
Wenn du das in der Actionlistener-Methode (die Methode die aufgerufen wird wenn der User auf einen Button klickt oder sonst irgendwie mit der GUI arbeitet) machst wird es der AWT-thread sein. Während der AWT-thread in wait() auf die anderen wartet funktioniert die GUI gar nicht. Sie wird auf nix reagieren und nix anzeigen. Der User kann also 1. nicht sehen dass die Sortierung schon läuft und 2. sie auch nicht unterbrechen.
Also sollte man das NICHT im AWT-thread machen. Das geht anders besser:
Du baust dir ein zentrales Objekt DATA das alle Werte bekommt. In dem Object geben die Sortier-threads ihre Werte ab und kucken ob sie weitermachen sollen oder nicht. (Polling)
So in der Art
public synchronized boolean lastValues (int[] aktuelles_array, int SortiererID)
(Das int[]-array sollte eine Kopie sein oder kopiert werden. Nicht einfachso im Rechenthread und in DATA das gleiche Array verwenden)
Wenn das false zurückgibt soll sich der Thread erstmal schlafen legen, und zwar in DATA.wait(). Klickt der User auf „noch einen Schritt rechnen“ (oder "ganz-zuende-rechenen) rufts du DATA.notifyAll() auf. Dadurch laufen die sortier-threads wieder weiter. Wenn das Prog eh von anfang an durchlaufen soll kann die Methode auch immer true zurückgeben. Bei true sollen die Threads nicht warten und nicht „wait()“ aufrufen.
Damit wären die Daten schonmal threadsafe eingesammelt und die GUI funktioniert auch noch.
Bleibt noch das anzeigen:
Jetzt kommt wieder ein dummes Problem mit dem AWT-Thread: man kann in lastValues sich einfachso einen graphic-kontext (graphics2D-Object) besorgen und die Darstellung aktualiserien ABER:
Das führt fast immer zu Darstellungsfehlern. Deshalb gibt es „repaint()“ und „invokeLater(Runnable R)“. Für deine Zwecke (und eine gute Note) reicht „repaint(10)“. Du lässt DATA von JComponent erben und überschreibst (überlädest… wie sagt man das im Deutschen ?) „public synchronized void paint(Graphics g)“. (Das synchronized ist wichtig. Ohne wirst du diverse Multi-thread-Probleme aus dem 1-3 Semster in der Praxis kennenlernen) In der Methode malst du auf Basis der aktuellen Werte die Diagramme neu. paint darf nur im AWT-Thread ausgeführt werden… den man ja nicht aufhalten soll. Also ruft man ihn in lastValues mit „DATA.repaint(10)“. Daraufhin versucht der AWT-Thread möglichst bald „DATA.paint(Graphics g)“ aufzurufen.
Damit werden die Daten auch einigermassen schnell angezeigt. Es geht noch schneller, aber dann muss man gut auf Swing-Komponenten aufpassen.
Was das Starten der Threads angeht:
… User hat festgelegt welche Methoden er sehen will …
Runnable[] R = new Runnable [Anzahl_der_sortierer];
for (…){
bestimme zuständige Klasse/subklasse
initalisiere sie
trage sie in R[i] ein.
}
for (…){
R[i].start();
}
Wieso mit 2 Schleifen: „initalisiere sie“ wird etwas länger dauern als start(), die ersten Threads hätten somit einen erheblichen Zeitvorsprung bekommen. Deshalb 2 Schleifen.
Wieso start() und nicht run() ?
Neue Threads werden mit start() gestartet. run() ist nur eine normale Methode und würde für ein bisschen Verwirrung sorgen. (der AWT-Thread würde den ersten Sortierer bis zum Ende durchrechnen, dann den zweiten, dann den dritten… usw)
(R[] kann man danach entsorgen, das braucht man nicht mehr. Wenn man eine „alle-sind-fertig“ Kontrolle haben möchte sollten sich fertige Sortier-threads bei DATA abmelden.)
Das ganze geht auch noch eleganter, aber dann sollte man sich definitiv GUT mit Threads auskennen.
Wenns zu schnell war poste nochmal. Dann will ich aber auch wissen welche Uni/Fachhochschule die Frage gestellt hat.
cu