# Threading



## bladepit (6. Mai 2012)

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?


```
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 (6. Mai 2012)

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 (6. Mai 2012)

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 (6. Mai 2012)

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


----------



## XHelp (6. Mai 2012)

bladepit hat gesagt.:


> nur leider werden die Ausgaben erst dann angezeigt, wenn der Thread durch gelaufen ist.





bladepit hat gesagt.:


> Möchte mein Program solange blockieren bis dieser fertig ist und dann halt die Ausgaben anzeigen.


Also du musst dich schon entscheiden, was du willst.


----------



## bladepit (6. Mai 2012)

@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 (6. Mai 2012)

bladepit hat gesagt.:


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




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

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


----------



## steffomio (6. Mai 2012)

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


```
new Thread() {

    //your class fields

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

}.start();
```


----------



## steffomio (6. Mai 2012)

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


```
synchronized (yourComponentOrPanelOrWhatever.getTreeLock()) {
    //work on yourComponentOrPanelOrWhatever
}
```


----------



## bladepit (7. Mai 2012)

@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 (7. Mai 2012)

Sollte das nicht auch funktionieren?


```
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 (7. Mai 2012)

Hi,
ich vermute, dass dein Problem in der Schleife:

```
while(pdl.isAlive()) { ...
```
liegt.
Lass es den pdl Thread für andere Aufgaben sleepen, oder …. verwende eine andere Ablaufslogik.


----------



## JavaProfi (7. Mai 2012)

steffomio hat gesagt.:


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



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 (7. Mai 2012)

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.

```
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 (7. Mai 2012)

@ JP (JavaProfi),
hast du das:


```
... 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 (7. Mai 2012)

bladepit hat gesagt.:


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


----------



## JavaProfi (7. Mai 2012)

GeorgA hat gesagt.:


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



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



GeorgA hat gesagt.:


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


----------



## bladepit (7. Mai 2012)

Leider werde ich das wohl net mehr packen dann.

Gut dann isses so. Trotzdem danke


----------



## GeorgA (7. Mai 2012)

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"!


----------



## bladepit (7. Mai 2012)

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 (7. Mai 2012)

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:


```
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:


```
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 (7. Mai 2012)

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 (7. Mai 2012)

GeorgA hat gesagt.:


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



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



GeorgA hat gesagt.:


> Lass dich nicht von irgendwelchen Schlaumacher irritieren.



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

Gruß
JP


----------



## GeorgA (8. Mai 2012)

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


----------

