Threads und Swing

Carcharoth

Bekanntes Mitglied
Guten Abend

Ich habe die Klasse UF deren Konstruktor im EDT aufgerufen wird.
Darin wird abwechslungsweise etwas mit einer Berechnung gemacht (ausserhalb des EDT) und diverses an einer GUI gemacht (im EDT).

Wie kann ich sicherstellen, dass die eine Arbeit eines anderen Threads fertig ist, bevor ich mit der nächsten Arbeit anfange?

In der Berechnung möchte ich z.B. die GUI mit einem Progress updaten. Greife ich aber "zu früh" darauf, ist die Initialisierung der GUI vielleicht noch nicht fertig und ich kriege ein Fehler.

Java:
public UF() {
        setSize(800, 600);
        setLocationRelativeTo(null);
        contentPane = getContentPane();
        contentPane.setLayout(null);
        contentPane.add(new TreePanel(50,50,300,400, this));
        
        new Thread(new Runnable() {
            public void run() {
                // hier wird die Berechnung initialisiert.
                
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        // hier wird eine grafische Darstellung auf der GUI mit dem Anfangszustand der Berechnung initialisiert
                    }
                });
                
                // BERECHNUNG: hier wird eine längere Berechnung in einer Klasse "Berechnung" gemacht
                                
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        // hier wird das Ergebnis der Berechnung in der grafische Darstellung auf der GUI ausgegeben
                    }
                });
            }
        }).start();
    }
 
Beste Antwort
Folgendes habe ich gemeint zu verstehen: alles was mit der GUI zu tun hat muss im EDT passieren - dies erreiche ich z.B. im SwingUtilities.invokelater.
Ja, aber wirklich nur das, was mit der UI zu tun hat und nichts anderes. Und auch nur, wenn Du nicht eh schon im EDT bist!

Alles andere (insbesondere alles was den EDT verzögern könnte - wie z.B. eine lange Berechnung - muss ausserhalb des EDT passsieren.
Ist das falsch ?
Nein, das ist auch richtig.
Wie müsste ich also folgende Aufgaben "thread-technisch" organisieren?
1 - GUI einrichten (setSize, setLayout, usw.)
Das sind Dinge, die gemacht werden, wenn das Fenster auch aufgebaut wird. Du hast also eine Klasse, die das Fenster erstellt und so und deren Dinge...

KonradN

Super-Moderator
Mitarbeiter
Die Initialisierung findet im EDT statt.
Die Resultate schreibst du ja mit SwingUtilities auch im EDT.

=> Das Problem kann nicht auftreten. Die Veränderung der UI ist ja ein Event, das in die Queue des EDT geschrieben wird. Das bearbeitet der EDT ja erst dann, wenn der EDT mit der Initialisierung fertig ist.

Auf der UI kann es also nur zu Problemen kommen, wenn einzelne Events Abhängigkeiten haben aber wenn du im EDT UI aufbaust und dabei einen Hintergrundjob abstattest, dann kommen die Ergebnisse immer erst an, wenn der EDT fertig ist.

Die UI bearbeitet nur der EDT und daher nur 1 Thread der zugreift und damit keine solchen Konflikte.
 

KonradN

Super-Moderator
Mitarbeiter
Und da ich den Code wieder sehe: das mit Lambda Expression oder Methodenreferenz hat Dir nicht gefallen? Oder brauchst du da mehr Erklärungen?
 

Neumi5694

Top Contributor
Das scheint mir ein etwas seltsamer Aufbau zu sein ...
invokeLater ist dazu da, dass der Code erst ausgeführt wird, wenn alle anderen UI-Aufgaben abgehandelt wurden, du kannst so z.B. die Reaktion auf die Änderung einer Listenauswahl oder der Kontextmenütaste verzögern, um sicherzustellen, dass zu dem Zeitpunkt auch wirklich alles schon geändert wurde. Wenn ein Thread die UI ändert, dann sollte im Normalfall direkt passieren.
Invokelater von einem Thread aus aufzurufen, ist also sinnlos, da der UI Thread außerhalb des Bereichs eh nicht angesprochen wird. Wenn der UI Thread gerade beschäftigt ist, dann kommt das, was du von ihm willst, eh in eine Queue.

Wenn sie eh aufeinander warten sollen, sind die beiden Subthreads sinnlos. Pack einfach die beiden Aufrufe direkt rein. Aber wenn du so was bauen willst, kannst du anstatt dem invokelater normale Threads verwenden und mit join warten.

Hast du dir schon den SwingWorker angeschaut? Bei dem kannst du auf verschiedene Events reagieren.
 

Neumi5694

Top Contributor
ps: Es gibt noch SwingUtils.invokeAndWait, das wäre vielleicht für die Initialisierung sinnvoll.

Du solltest aber auf keinen Fall Berechnungen im UI-Thread durchführen (also Finger weg von SwingUtilities bei der Berechnung)
 

Carcharoth

Bekanntes Mitglied
Und da ich den Code wieder sehe: das mit Lambda Expression oder Methodenreferenz hat Dir nicht gefallen? Oder brauchst du da mehr Erklärungen?
Doch hat mir gefallen, weil kompakt. Aber ich muss mir die Zeit nehmen, dass etwas besser anzuschauen. Ich möchte es verstehen und nicht einfach blind anwenden.

Das scheint mir ein etwas seltsamer Aufbau zu sein ...
Ich habe vermutlich die Geschichte mit Swing und den Threads noch nicht ganz verstanden.

Folgendes habe ich gemeint zu verstehen: alles was mit der GUI zu tun hat muss im EDT passieren - dies erreiche ich z.B. im SwingUtilities.invokelater.
Alles andere (insbesondere alles was den EDT verzögern könnte - wie z.B. eine lange Berechnung - muss ausserhalb des EDT passsieren.
Ist das falsch ?

Wie müsste ich also folgende Aufgaben "thread-technisch" organisieren?
1 - GUI einrichten (setSize, setLayout, usw.)
2 - Berechnung initialisieren (dauert etwas)
3 - grafische Darstellung in der GUI einrichten (muss zwingend nach der Initialisierung der Berechnung geschehen)
4 - Berechnung durchführen - dauert lange (mit der Möglichkeit den Progress in der GUI anzuzeigen)
5 - grafische Darstellung in der GUI mit dem Endresultat der Berechnung abschliessend darstellen
 

KonradN

Super-Moderator
Mitarbeiter
Folgendes habe ich gemeint zu verstehen: alles was mit der GUI zu tun hat muss im EDT passieren - dies erreiche ich z.B. im SwingUtilities.invokelater.
Ja, aber wirklich nur das, was mit der UI zu tun hat und nichts anderes. Und auch nur, wenn Du nicht eh schon im EDT bist!

Alles andere (insbesondere alles was den EDT verzögern könnte - wie z.B. eine lange Berechnung - muss ausserhalb des EDT passsieren.
Ist das falsch ?
Nein, das ist auch richtig.
Wie müsste ich also folgende Aufgaben "thread-technisch" organisieren?
1 - GUI einrichten (setSize, setLayout, usw.)
Das sind Dinge, die gemacht werden, wenn das Fenster auch aufgebaut wird. Du hast also eine Klasse, die das Fenster erstellt und so und deren Dinge laufen im EDT. Da musst Du also gar nichts machen.
2 - Berechnung initialisieren (dauert etwas)
Die Berechnung wäre also irgend etwas Externes. Also eine eigene Klasse oder so. Die Berechnung erfolgt in einem eigenen Thread. Wenn die Berechnung fertig ist, dann kannst Du der Klass emit dem Fenster Bescheid geben. Die Klasse hat dann also eine Methode displayResults(....) und da werden fertige Ergebnisse übergeben. Da Du aber in der Berechnung weisst, dass Du in einem eigenen Thread bist, musst Du hier invokeLater verwenden. Also etwas wie
SwingUtilities.invokeLater( () -> classInstanceWithWindow.displayResults(result1, result2, result 3) );

Alternativ kann man auch den SwingWorker nutzen. Der hat bereits entsprechende Methoden, die dann im EDT ablaufen um z.B. nach der Berechnung die Ergebnisse zu setzen.

3 - grafische Darstellung in der GUI einrichten (muss zwingend nach der Initialisierung der Berechnung geschehen)
Das passiert dann ja in displayResults. Da machst Du aber nichts mit EDT. Du gehst davon aus, dass Du im EDT bist.
4 - Berechnung durchführen - dauert lange (mit der Möglichkeit den Progress in der GUI anzuzeigen)
1:1 wie in 2.
5 - grafische Darstellung in der GUI mit dem Endresultat der Berechnung abschliessend darstellen
Und das ist wieder so wie in 4.

Der generelle Aufbau einer Swing Anwendung ist meist:
  • in der main wird nur das Fenster erstellt und damit die Anwendung gestartet. Sonst absolut nichts!
  • dadurch hast Du erst einmal alles im EDT. Das ist also an der Stelle ein Punkt, über den Du nicht nachdenken musst.
  • erst wenn Du irgendwas in einem anderen Thread machst, dann musst Du da aufpassen. Daher ist es ratsam, das in einer eigenen Klasse zu machen und zu kapseln. Da kannst Du dann alles machen was Du willst - nur eben nicht auf die UI zugreifen! Bei allen UI Zugriffen musst Du dann in dieser Klasse den Wechsel vollziehen. Also ein SwingUtility.invokeLater nutzen.

Und gerade diesen letzten Punkt wurde in jedem Framework schon für Dich gemacht. Swing hat den SwingWorker, .Net hat bei WindowsForms den BackgroundWorker u.s.w. Da hast Du dann eine klare Aufteilung in Dinge, die Du machen kannst.

SwingWorker hat dazu
  • doInBackground: Der Name sagt es ja schon - das passiert im Hintergrund in einem eigenen Thread. Also keine UI Zugriffe.
  • process: Läuft im EDT und dient dazu, zwischenergebnisse darzustellen.
  • done: Auch EDT, läuft wenn doInBackground fertig ist.

Zu den Hintergründen: process wird angetriggert durch publish. In doInBackground kannst Du also einfach publish aufrufen. Das macht dann unter dem Strich eben genau dieses invokeLater von dem publish.
 
Beste Antwort

Neumi5694

Top Contributor
Wenn du eine Berechnung im Hintergrund machst und die UI für die einzelnen Schritte aktualisiert weden muss, dann reicht ein einzelner Thread für die Berechnung, der dann deinem Formular mitteilt - ganz ohne zweiten oder dritten Thread - dass es aktualisiert werden soll.
Damit brauchst du dann auch nichts extra zu programmieren, um auf die UI zu warten. Der SwingWorker stellt eine elegantere Methode dar, ist eben dafür gedacht, dass bei UIs etwas im Hintergrund passoert, ist manchmal aber etwas Overkill.

In keinem Fall musst du Threads (oder Worker) in andere Threads verpacken. Das ist ausschließlich dann sinnvoll, wenn für die Aufgabe des Hauptthreads mehrere Sachen gleichzeitig passieren sollen und dann sollte man sich überlegen, ob man das ordentlich durchgeplant hat.
Sobald deine Berechnung in einem Hintergrundthread stattfindet, kann der UI-Thread normal weiterlaufen, da musst du nichts mehr tun. Da brauchst du auch kein invokeLater. Das ist im Normalfall wirklich nur dann sinnvoll, wenn sich mehrere UI-Listener in die Quere kommen können.

Ich hab z.B. auf die rechte Maustaste in einer Tabelle reagiert, um ein Kontextmenü anzuzeigen. Dabei sollte aber auch die aktuelle Zeile auf die Zeile geändert werden, über der sich der Mauszeiger befindet.
Problem: Der Mouselistener reagierte, bevor die Zeile aktualisiert wurde. Ich hätte jetzt hergehen können und im Mouselistener die Zeile setzen und dann die Anzeige ausführen damit würden aber a) zu viele SelectionChange-Events ausgelöst und b) würden die Indizes vor allem beim Deselected-Teil nicht passen. Wenn da jetzt auch ein Listener dranhängt ... Problem. Außerdem b) ist es nicht notwendig, die UI wird die Änderung ja durchführen, es ist halt nur noch nicht passiert. Lösung: Ich packe das Handling des Mouselisteners in eine invokeLater. Damit wird es verzögert, bis alles andere inklusive der SelectionChangeListener abgeschlossen ist und erst danach die Anzeige gestartet.

Wenn du nur Änderungen darstellen willst (in einem Log etwa), ist es ja egal, wann die genau dargestellt werden. Du hast in dem Fall keinen Grund, auf irgendwas in der UI zu warten, bevor die Werte angezeigt werden.
 

mrBrown

Super-Moderator
Mitarbeiter
Das scheint mir ein etwas seltsamer Aufbau zu sein ...
invokeLater ist dazu da, dass der Code erst ausgeführt wird, wenn alle anderen UI-Aufgaben abgehandelt wurden, du kannst so z.B. die Reaktion auf die Änderung einer Listenauswahl oder der Kontextmenütaste verzögern, um sicherzustellen, dass zu dem Zeitpunkt auch wirklich alles schon geändert wurde. Wenn ein Thread die UI ändert, dann sollte im Normalfall direkt passieren.
Invokelater von einem Thread aus aufzurufen, ist also sinnlos, da der UI Thread außerhalb des Bereichs eh nicht angesprochen wird. Wenn der UI Thread gerade beschäftigt ist, dann kommt das, was du von ihm willst, eh in eine Queue.

Eher andersrum: Änderungen an der UI sollten immer über den UI-Thread gemacht werden. Swing ist (zum Großteil) nicht Threadsafe, und wenn man aus eigenen Threads drauf zugreift, greift man parallel zum UI-Thread drauf zu. Das kann gut gehen, kann aber irgendwann plötzlich knallen, ohne jegliche Änderung am Programm - daher besser gleich richtig machen.

Siehe zB https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
 

Neumi5694

Top Contributor
Eher andersrum: Änderungen an der UI sollten immer über den UI-Thread gemacht werden. Swing ist (zum Großteil) nicht Threadsafe, und wenn man aus eigenen Threads drauf zugreift, greift man parallel zum UI-Thread drauf zu. Das kann gut gehen, kann aber irgendwann plötzlich knallen, ohne jegliche Änderung am Programm - daher besser gleich richtig machen.

Siehe zB https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
Ich meinte die Berechnung, nicht die UI-Änderungen (war wohl etwas unglücklich ausgedrückt).
Das Formular oder worum es auch immer sich bei dem Logger handelt, sollte dann eine Methode bieten, über welche Änderungen erwirkt werden und sich selbst darum kümmern. Die Berechnungsmethode selbst sollte von der UI gar nichts wissen, im Normalfall noch nicht mal wisse, ob es sich um eine UI handelt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Q Threads Threads in Swing Anwendungen Java Basics - Anfänger-Themen 5
C Swing i.V.m. Threads Java Basics - Anfänger-Themen 2
Luk10 Swing timer und Threads Java Basics - Anfänger-Themen 4
hdi Performance Frage (Threads,Swing) Java Basics - Anfänger-Themen 4
B Fragen zu threads, swing, und dem bytecode compiler, etc. Java Basics - Anfänger-Themen 4
P Verständnisfrage zu Threads (und Swing) Java Basics - Anfänger-Themen 8
H Nutzt Eclipse alle CPU-Threads beim Ausführen von Java-Programmen? Java Basics - Anfänger-Themen 4
berserkerdq2 Wo finde ich in der Java Api die Notation zu Threads bezüglich Synchronized? Java Basics - Anfänger-Themen 14
berserkerdq2 Findet eine parallele Verarbeitung in Java bei Threads erst statt, wenn man die Methoden auch synchronized? Und wie sieht bei Conditions aus? Java Basics - Anfänger-Themen 8
B Monitor als Schranke von Threads Java Basics - Anfänger-Themen 20
W Threads Alphabet Java Basics - Anfänger-Themen 20
H Threads Anfänger Java Basics - Anfänger-Themen 17
1 Threads parallel laufen Java Basics - Anfänger-Themen 11
B Threads Problem mit mehreren Threads Java Basics - Anfänger-Themen 38
M Threads Java Basics - Anfänger-Themen 12
L Threads Synchronisierung zwischen threads Java Basics - Anfänger-Themen 4
M Threads Java Basics - Anfänger-Themen 2
A Threads Java Basics - Anfänger-Themen 9
A Threads Java Basics - Anfänger-Themen 13
A Threads und .join Java Basics - Anfänger-Themen 14
W Threads starten Java Basics - Anfänger-Themen 2
X Threads Zwei Threads, aber doppelte Ausgabe verhindern (synchronized) Java Basics - Anfänger-Themen 54
J Wieviele threads? Java Basics - Anfänger-Themen 9
J Problem bei seriellem Start von Threads Java Basics - Anfänger-Themen 11
O Threads Java Basics - Anfänger-Themen 2
L Buchungssystem und Threads Java Basics - Anfänger-Themen 2
O Threads - Synchronize(), join(), wait(), notify(), yield() Java Basics - Anfänger-Themen 6
L Klassen NFC Reader und JavaFx Problem -> threads? Java Basics - Anfänger-Themen 2
A Kommunikation zwischen nebenläufigen Threads Java Basics - Anfänger-Themen 4
S Gemeinsame Ressource und Mehrfachinstanziierung von Threads Java Basics - Anfänger-Themen 16
S Verklemmung Threads Java Basics - Anfänger-Themen 11
B Threads 2 Threads gleichzeitig laufen lassen Java Basics - Anfänger-Themen 1
M Threads Threads laufen sequenziell, statt gleichzeitig. Java Basics - Anfänger-Themen 9
M Threads run Methode Java Basics - Anfänger-Themen 4
javajoshi mehrere Threads: Methoden zentral unterbringen Java Basics - Anfänger-Themen 8
javajoshi Problem mit zwei Threads und Arrays (Runnable) Java Basics - Anfänger-Themen 12
L Threads Mit Threads JLabel ändern! Java Basics - Anfänger-Themen 2
K Matrixen berechnen nach Worker Master Paradigma mit Threads Java Basics - Anfänger-Themen 4
S Kleine Frage zu Threads Java Basics - Anfänger-Themen 3
M Mit 2 Threads eine Zahl hochzählen Java Basics - Anfänger-Themen 13
T Threads Synchronisieren Java Basics - Anfänger-Themen 6
D Frage Threads Java Basics - Anfänger-Themen 6
Z Threads Executor Framework - Aufgabe auf n Threads aufteilen Java Basics - Anfänger-Themen 10
Z Threads Threads - Zugriff auf Ressourcen ohne(Lock, Synchronized) Java Basics - Anfänger-Themen 2
kilopack15 Verständnisfrage zur Verwendung von notify() bei Threads Java Basics - Anfänger-Themen 2
kilopack15 Mehrere Threads in einer Klasse Java Basics - Anfänger-Themen 8
H Threads funktionieren nicht Java Basics - Anfänger-Themen 4
J Aufgabe(Threads) richtig verstanden/implementiert Java Basics - Anfänger-Themen 27
R Threads aufeinander warten lassen? Java Basics - Anfänger-Themen 10
T Threads Durch threads gestartete Prozesse killen Java Basics - Anfänger-Themen 2
J Threads Java Basics - Anfänger-Themen 38
D Alte Klausuraufgabe Threads Java Basics - Anfänger-Themen 10
A Threads Threads bestimmte Aufgaben zuweisen... Java Basics - Anfänger-Themen 3
R Threads in JavaFX Java Basics - Anfänger-Themen 3
E Threads Doppelte Threads beenden Java Basics - Anfänger-Themen 4
F Sicheres Zurückmelden aus Threads Java Basics - Anfänger-Themen 0
G Threads zum Thema Threads??? null Ahnung Java Basics - Anfänger-Themen 4
J ConcurrentCalculation Multi Threads in Java Java Basics - Anfänger-Themen 3
P Threads Trotz Threads wird nur 1 Prozessorkern ausgelastet Java Basics - Anfänger-Themen 7
M "restartable" threads Java Basics - Anfänger-Themen 11
M Threads - summieren Java Basics - Anfänger-Themen 13
W Klassen Variable einer anderen Klasse ändern (Threads) Java Basics - Anfänger-Themen 3
E Threads - Programm analysieren Java Basics - Anfänger-Themen 2
E join() bei zwei Threads Java Basics - Anfänger-Themen 2
T Threads Threads richtig synchronisieren Java Basics - Anfänger-Themen 3
D [Concurrency/Threads] Code Umsetzung Schriftlich Java Basics - Anfänger-Themen 2
D Threads Java Basics - Anfänger-Themen 4
M Threads nio Dateien kopieren, Threads und Gui Java Basics - Anfänger-Themen 0
N Verweise auf Variablen in verschiedenen Threads Java Basics - Anfänger-Themen 4
T Java-Threads Java Basics - Anfänger-Themen 0
G Moving Objects with Threads (implements Runnable) Java Basics - Anfänger-Themen 1
F Threads funktionieren auf JPanel nicht Java Basics - Anfänger-Themen 1
M Problem mit Threads Java Basics - Anfänger-Themen 11
M Threads - wo gehören sie hin? Java Basics - Anfänger-Themen 3
S 2D-Spiel mit Threads... Java Basics - Anfänger-Themen 3
J Threads Java Basics - Anfänger-Themen 3
F ExecutorService und offene Threads Java Basics - Anfänger-Themen 3
P Threads Threads nicht nebenläufig Java Basics - Anfänger-Themen 7
M Threads nicht nebenleblaufig Java Basics - Anfänger-Themen 2
B Threads parallel zur main Java Basics - Anfänger-Themen 3
M Threads Java Basics - Anfänger-Themen 2
M Threads, zwei methoden gleichzeitig laufen lassen Java Basics - Anfänger-Themen 4
M Threads und Methodenübergreifender Variablezugriff Java Basics - Anfänger-Themen 2
J Wie handle ich Threads am besten? Java Basics - Anfänger-Themen 2
H Threads Java Basics - Anfänger-Themen 10
B synchronized threads Java Basics - Anfänger-Themen 17
E Mehrmaliges Ausführen eines Threads Java Basics - Anfänger-Themen 5
E Threads Verständnisfrage bzgl. Threads und Sleep Java Basics - Anfänger-Themen 2
T Alle Threads .notify() Java Basics - Anfänger-Themen 13
R Threads Verständnisschwierigkeit Java Basics - Anfänger-Themen 2
J Können mehere Threads parallel eine Datei lesen? Java Basics - Anfänger-Themen 4
G Methoden in Threads wandeln Java Basics - Anfänger-Themen 7
H Threads Java Basics - Anfänger-Themen 17
F Java Concurrency - Threads Java Basics - Anfänger-Themen 4
V Threads Threads synchronisieren Java Basics - Anfänger-Themen 4
T Threads Join() = Block? oO Java Basics - Anfänger-Themen 4
J Threads ArrayList Problem bei Threads Java Basics - Anfänger-Themen 3
C Objekte durchschleifen / Threads Java Basics - Anfänger-Themen 2
J Threads stoppen mit interrupt - Frage dazu Java Basics - Anfänger-Themen 7
N Pingen in Threads Java Basics - Anfänger-Themen 9

Ähnliche Java Themen

Neue Themen


Oben