Threading

bladepit

Bekanntes Mitglied
Hallo zusammen,

ich habe eine Frage zu Threads. Ich habe einen Thread der SQL-Abfragen ausführt. Diese Ausgaben möchte ich dann einem Frame anzeigen nur leider werden die Ausgaben erst dann angezeigt, wenn der Thread durch gelaufen ist.

Ich weiß aber nicht warum. Ich starte den Thread bevor ich das Frame erzeuge und mache dann eine while-Schleife die solange läuft bis der Thread durch ist. Innerhalb dieser Schleife möchte ich dann die Ausgaben aus den SQL-Abfragen innerhalb des Frames anzeigen.

Sieht einer den Fehler?

Java:
pdl.start();

JFrame nframe = new JFrame("Load Data");
JLabel out = new JLabel();
nframe.add(out);
nframe.setVisible(true);

String stat = null;
while(pdl.isAlive()){
	if(stat != pdl.getStatus()){
		stat = pdl.getStatus();
		System.out.println(stat);
		out.setText(stat);
		nframe.repaint();
	}
}

Die Ausgabe auf der Konsole kommt aber im Fenster wird erst dann was angezeigt wenn die Schleife durch ist.

Gruß

bladepit
 

XHelp

Top Contributor
Wo steht dieser Code? Sind das einzelne Teile von irgendwoher oder wie?
Wenn das alles in einer Klasse steht, dann machst du dir ja deinen Thread zu nichte, da du mit einer while-Schleife die Sachen abfragst.
 

bladepit

Bekanntes Mitglied
Ja das steht alles in einer Klasse.

Das ich mir den Thread damit kaputt mache ist klar. Will ich im Prinzip auch. Möchte mein Program solange blockieren bis dieser fertig ist und dann halt die Ausgaben anzeigen.

Habe andere Teile wo die Threads laufen während andere Sachen gemacht werden.
 

Robokopp

Bekanntes Mitglied
Vor einem ähnlichen Problem stand ich auch vor einiger Zeit.
Du musst halt zusehen, dass Berechnungen von einem neuen Thread aus gestartet werden, d.h. zum Beispiel:

Buttonklick started Thread -> run() Methode ruft Methode zum Berechnen auf.

Der Rest des Programms bleibt dann im Mainthread, wie auch die Zeichenmethode.

EDIT:

Wenn du nämlich beides im selben Thread laufen lässt, wird die paint Methode solange blockiert, bis die Schleife durchgelaufen ist
 

bladepit

Bekanntes Mitglied
@XHelp: Sorry meine natürlich Ausgaben solange der Thread läuft.

Was ich daran nicht verstehe ist, dass ich ja den Thread starte und damit ja die Anzeige weiter im normalen Program laufen kann. Der Thread blockiert das ja nicht mehr sondern die Schleife.
 

JavaProfi

Aktives Mitglied
Hallo zusammen,

ich habe eine Frage zu Threads. Ich habe einen Thread der SQL-Abfragen ausführt. Diese Ausgaben möchte ich dann einem Frame anzeigen nur leider werden die Ausgaben erst dann angezeigt, wenn der Thread durch gelaufen ist.

Ich weiß aber nicht warum. Ich starte den Thread bevor ich das Frame erzeuge und mache dann eine while-Schleife die solange läuft bis der Thread durch ist. Innerhalb dieser Schleife möchte ich dann die Ausgaben aus den SQL-Abfragen innerhalb des Frames anzeigen.

Sieht einer den Fehler?

Die Ausgabe auf der Konsole kommt aber im Fenster wird erst dann was angezeigt wenn die Schleife durch ist.

Gruß

bladepit


Zu deinem Problem!
Jede Änderung an einer Swing-Komponente muss im EDT ausgeführt werden.
Dazu die Änderungsanweisung in ein Runnable packen und in die EventQueue des EDT stellen.
In deinem Beispiel willst du auf die Anzeige des Ergebnisses warten.
Insofern nicht mit EventQueue.invokelater(...) das Runnable in die Warteschlange des EDT stellen sondern mit EventQueue.invokeAndWait(...)

Dein Code gibt nicht genügend her, aber ungefähr so...
Java:
pdl.start();
JFrame nframe;
JLabel out;
EventQueue.invokeLater( new Runnable()
{
  public void run() {
     nframe = new JFrame("Load Data");
     out = new JLabel();
     nframe.add(out);
     nframe.setVisible(true);
  }
} );

String stat = null;

while(pdl.isAlive()){
	if(stat != pdl.getStatus()){
		stat = pdl.getStatus();
		System.out.println(stat);
		EventQueue.invokeAndWait( new Runnable()
		{
		  public void run() {
		       out.setText(stat);
		  }
		} );
	}
}
Gruß
JP
 
Zuletzt bearbeitet:

steffomio

Mitglied
Mal Grundsätzlich:
Ein einfacher Thread geht z.B. so:

Java:
new Thread() {

    //your class fields

    @Override
    public void run() {
        //your code
    }
    
    private <whatever> yourMethods(){
        // more code
    }

}.start();
 

steffomio

Mitglied
Und wenn du mit Threads und Components arbeitest, solltest du arbeiten an Components mit einem TreeLock absichern.
Das geht so:

Java:
synchronized (yourComponentOrPanelOrWhatever.getTreeLock()) {
    //work on yourComponentOrPanelOrWhatever
}
 

bladepit

Bekanntes Mitglied
@JP das sieht ganz gut aus nur das er mit final dann Probleme bekommt.

Ich soll das Frame, das Label und die Stat-Variable final machen nur das ich die dann ja nicht mehr verändern darf.
 

bladepit

Bekanntes Mitglied
Sollte das nicht auch funktionieren?

Java:
				pdl.start();
				
				new Thread(new Runnable() {
	        		  public void run() {
	        			nframe = new JFrame("LoadData");
	        			out=new JLabel("Jall");
	        			nframe.add(out);
	        			nframe.setVisible(true);
	        		  }}).start();
				
				while(pdl.isAlive()){
				    if(stat != pdl.getStatus()){
				        stat = pdl.getStatus();
				        new Thread(new Runnable() {
			        		  public void run() {
			        			  out.setText(stat);
			        			  System.out.println(stat);
			        		  }}).start();
				    }
				}
 

GeorgA

Mitglied
Hi,
ich vermute, dass dein Problem in der Schleife:
Java:
while(pdl.isAlive()) { ...
liegt.
Lass es den pdl Thread für andere Aufgaben sleepen, oder …. verwende eine andere Ablaufslogik.
 

JavaProfi

Aktives Mitglied
Mal Grundsätzlich:
Ein einfacher Thread geht z.B. so:

Java:
new Thread() {

    //your class fields

    @Override
    public void run() {
        //your code
    }
    
    private <whatever> yourMethods(){
        // more code
    }

}.start();

Willkommen im Club "Ich habe gar nichts kapiert".
Es geht hier nicht darum wie man einen Thread programmiert, sondern darum, dass SWING nicht Thread-sicher ist, weil es nicht wie AWT die proprietären Componenten des Betriebsystem nutzt. Um das Problem zu lösen haben die JAVA Entwickler den EDT eingeführt. Bitte erst schlau machen, dann posten !!

Für dich zum nachlesen:

Initial Threads (The Java™ Tutorials > Creating a GUI With JFC/Swing > Concurrency in Swing)
 

steffomio

Mitglied
Wenn ich dich richtig verstanden habe, dann wir ich da so ran gehen:
Die sichtbaren Elemente werden meines Wissens mit sehr geringer Priorität aktualisiert.
Denn so lange dein Code alle Power weg saugt, wird sich da gar nichts sichtbares von Swing aktualisieren.
Java:
new Thread() {
    public void run() {
        ing stat = null;
        while (pdl.isAlive()) {
            try{
                // prevent consume all cpu power
                Thread.sleep(100);
            }catch(Exception ignore){
                // ignore
            }
            if (stat != pdl.getStatus()) {
                stat = pdl.getStatus();
                System.out.println(stat);
                synchronized (nframe.getTreeLock()) {
                    out.setText(stat);
                    nframe.repaint();
                }
            }
        }
    }
}.start();
 

GeorgA

Mitglied
@ JP (JavaProfi),
hast du das:

Java:
... while(pdl.isAlive()){
    if(stat != pdl.getStatus()){
        stat = pdl.getStatus();
        System.out.println(stat);
        EventQueue.invokeAndWait( new Runnable()...

auch getestet? (nein – weil keiner den pdl Source zu sehen bekommen hat.)
Alles anderes ist nur Vermutung, Spekulationen ….

EventQueue.invokelater(...) bzw. EventQueue.invokeAndWait(...) wirken bei Mulitrhreading. ...
hier (Bei der Anfangsfrage) ist das vermute nicht der Fall .
… Ich habe einen Thread der SQL-Abfragen ausführt. Diese Ausgaben möchte ich dann einem Frame anzeigen …

Der möchte einfach nur die DB abfragen, und den Result einfach visualisieren (Anzeigen lassen).
Hier etabliert sich;
Eine Klase für die DB abfragen (ok als Thread)
Und eine weitere (separate – neue) Klase für die Visualisierung.

Gruß
Georg
 

JavaProfi

Aktives Mitglied
@JP das sieht ganz gut aus nur das er mit final dann Probleme bekommt.

Ich soll das Frame, das Label und die Stat-Variable final machen nur das ich die dann ja nicht mehr verändern darf.

Wenn du nicht mit final arbeiten möchtest, dann gibt zwei Möglichkeiten:

1)
Du schreibst eine eigene Klasse die das Interface Runnabel implementiert und die Modifikationen an der SWING-Komponente durchführt. In der Konstruktor-Methode übergibst du eine Referenz auf dein JFrame-Objekt.
Die Instanz dieser Klasse übergibst du dann an dem EDT mit invokelater() [asynchron] oder invokeAndWait() [synchron].

2)
Baue das Ganze was du vorhast in einen Swingworker!
Das ist eine sehr elegante Lösung der JAVA-Entwickler, die SWING-Modifikation durchzuführen.
Im Endeffekt macht ein Swingworker nichts anderes als das, was du hier manuell programmieren willst.

Erklärt ist das sehr schön hier:
SwingWorker ? Byte-Welt Wiki

Siehe auch mein Posting hier:

http://www.java-forum.org/allgemeine-java-themen/134628-sudoku-threads.html#post886436

Gruß
JP
 
Zuletzt bearbeitet:

JavaProfi

Aktives Mitglied
@ JP (JavaProfi),
Alles anderes ist nur Vermutung, Spekulationen ….

Hallo Georg.
Nein keine Vermutung sondern meine lange Programmiererfahrung mit JAVA.

@ JP (JavaProfi),

EventQueue.invokelater(...) bzw. EventQueue.invokeAndWait(...) wirken bei Mulitrhreading. ...
hier (Bei der Anfangsfrage) ist das vermute nicht der Fall .

Lese dich bitte mal in die SWING-Direktiven von JAVA ein!
Ich weiß, das ist schwerer Stoff, aber wenn man mit SWING programmiert MUSS man das mit dem EDT verstehen. Dann kannst du dir die Antwort auf diese Frage selber geben.

Zum Nachschlagen:
Threads and Swing

Using a Swing Worker Thread

http://www.java-forum.org/allgemeine-java-themen/134628-sudoku-threads.html#post886436

Gruß
JP
 
Zuletzt bearbeitet:

GeorgA

Mitglied
Das ist die Falsche Antwort!
Du packt es schon!
Das Zauberwort heißt: Motivation, Ausdauer, Willenskraft …
Deine Aufgabe ist wirklich ziemlich leicht realisierbar.
Lass dich nicht von irgendwelchen Schlaumacher irritieren.

Wir "kriegen es hin"!
 
Zuletzt bearbeitet:

bladepit

Bekanntes Mitglied
Mir bringt das nur nix.
Hatte auf eine schnelle Hilfe gehofft anstatt les dich ein. Das ich das machen müsste ist mir auch klar.
Nur um 18 Uhr muss das entweder drin sein oder ich lass es.
Daher wird es verworfen
 

bladepit

Bekanntes Mitglied
So ich probiere es nochma auch wenn hier wieder einige ausrasten werden weil ich nicht genau weiß das da so passiert. Aber naja...

Also. Ich habe einen Button wenn ich da drauf klicke will ich:

1. Ein Fenster mit einem Label haben welches mir den Status eines SwingWorkers (SQL / InsgesamtSQLS) anzeigt.
2. Den Thread starten

So meine action-Methode sieht so aus, dass am Anfang einige Variablen gefüllt werden und dann der SwingWorker erstellt wird.

Der SwingWorker setzt die SQLs in doInBackground() ab. Zudem macht er nach jedem Durchlauf publish("HALLO NR." + i).

Process sieht dann so aus:

Java:
 protected void process(List<String> strings) {
		for(String a: strings){
			System.out.println(a);
			out.setText(a);
		}
    }

Eigentlich sollte diese Methode doch immer wenn publish gerufen wird ausgeführt werden oder? Bei mir passiert das erst am Ende.

Der SwingWorker wird nach dem Erstellen wie folgt ausgeführt:

Java:
 psw.execute();
               while(!psw.isDone()){
   				
               }

Bitte kein Lese ma hier mach ma da. Ich muss noch einige andere Sachen erledigen. Dies ist zwar nur Optional wäre aber super wenn das klappen würde daher bemühe ich mich das ans Laufen zu kriegen.
 

GeorgA

Mitglied
Zeitdruck, Hausaufgaben, XYZ- Arbeiten generieren bei mir …. Empörung .... .
Bei Teilproblem- Lösungen stehe ich gerne bei.
nun!
Ich schalte lieber auf Passiv.
Also bis irgendwann.

Gruß
Georg
 

JavaProfi

Aktives Mitglied
Zeitdruck, Hausaufgaben, XYZ- Arbeiten generieren bei mir …. Empörung .... .
Bei Teilproblem- Lösungen stehe ich gerne bei.
nun!
Ich schalte lieber auf Passiv.
Also bis irgendwann.

Gruß
Georg

Da muss ich GeorgA vollkommen Recht geben.
Das ist nicht Aufgabe dieses Forums!

Lass dich nicht von irgendwelchen Schlaumacher irritieren.

Ups, da fühlt sich wohl wer etwas angegriffen!

Gruß
JP
 

GeorgA

Mitglied
Vor einpaar Tagen, dürfte ich erfahren, dass mein jüngster Sohn (wohnt bei meiner Ex) mich massiv betrogen und belogen hat. Anstatt zur Schule, hat ganzes Jahr nur party gemacht und ist schließlich aus der Schule entlassen worden.
bladepit seiner Einstellung, wie auch deine Weisheit, hat wieder meine Wut auf "200" gebracht, meine Emotionen … und mein Benehmen eskalierte!:oops:
Ich möchte mich "dick" hier vor allen aber in besondern bei Dir JP zu entschuldigen. Es komm nie wieder vor.
Sorry
Gruß

@bladepit: - Deinem Problem, widme ich mich bei etwas Zeit.
 

Ähnliche Java Themen

Neue Themen


Oben