Übergabe einer Variable in einen neuen Thread?
lima-city → Forum → Programmiersprachen → Java
ausgabe
beenden
button
check
code
display
kopie
laufende anfrage
methode
objekt
parameter
referenz
run
schleife
setter
shell
start
wissen
zeigen
zeiger
-
Hallo, ich habe da ein kleines Problem, das ich nicht ganz verstehe.
Ich erstelle ein neues Objekt, das von einem Thread erbt. Über einen Parameter gebe ich dem Konstruktor des neuen Objekts eine Boolean Variable mit, die den Status einer Checkbox enthält. (Die Checkbox liegt außerhalb der Thread Klasse)
In der Run Methode des Thread Objekts rufe ich die Variable aus dem Konstruktor in einer while Schleife ab. Nun müsste man annehmen, dass sich der Wert in der Variable ändert, wenn ich die Checkbox benutze, was jedoch nicht passiert. In der Ausgabe hab ich dann sowas:
false
false
false
Button
false
false
Button
false
...
Außerhalb des Threads ändert sich die Variable, aber nicht im Thread selber oO.
Jetzt bin ich hartnäckig und habe in meiner Thread Klasse zusätzlich getter/setter für die Variable gemacht und aktualisiere diese mit dem event der Checkbox, was den Wert in meinem Thread auch wirklich ändert. Die Variable im Konstruktor ist eigentlich die Selbe, warum wird sie nicht aktualisiert?
Mein Konstruktor sieht übrigens so aus, das muss doch gehen ^^:
private boolean tagesumsatz; public AutoRefreshStockData(Shell shell, boolean tagesumsatz) { this.tagesumsatz = tagesumsatz; ... }
Beitrag zuletzt geändert: 18.11.2010 10:47:40 von cglabs -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Ich versuch es mal.
public class GUIComponents { private boolean tagesumsatz; private AutoRefreshStockData autorefresh; ... public void setCheckBox(final Shell shell){ final Button check = new Button(shell, SWT.CHECK); ... check.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { tagesumsatz = check.getSelection(); } }); } ... public void setTable(Shell shell){ ... Composite tableArea = new Composite(shell, SWT.NONE); tableArea.setLayout(new FillLayout()); fillTable = new FillTable(tableArea); ... // On Start autoRefreshTableStart(shell); ... } ... public void autoRefreshTableStart(Shell shell) { autorefresh = new AutoRefreshStockData(shell, tagesumsatz, ...); autorefresh.start(); } } public class AutoRefreshStockData extends Thread { private boolean tagesumsatz; ... public AutoRefreshStockData(Shell shell, boolean tagesumsatz, ...) { this.tagesumsatz = tagesumsatz; ... } @Override public void run() { while (!threadDone) { if (!display.isDisposed()) { display.asyncExec(new Runnable() { @Override public void run() { System.out.println(tagesumsatz); ... } }); } } } }
EDIT:
Ich habe noch eine zweite Frage, und zwar befindet sich in der while Schleife noch eine Methode, die Daten aus einem entfernten Server holt, was einige Sekunden dauert. Beim Beenden der Shell und des Displays läuft die Anfrage noch weiter und merkt irgendwann, dass die Shell nicht mehr da ist, was zu einer Fehlerausgabe führt (Device is disposed). Der Prozess wird eigentlich beendet, trotz Fehlermeldung. Muss man sich da sorgen machen, oder kann man das ignorieren?
Ich wüsste jetzt nicht, wie man eine laufende Anfrage beenden kann, bevor die Shell weg ist.
Beitrag zuletzt geändert: 18.11.2010 14:53:28 von cglabs -
Moin,
Du sagst die Variable ändert sich nicht innerhalb vom Thread?
Wenn ich mir Deinen Code so anschaue, kann das auch gar nicht geschehen, da Du nirgends den aktuellen Status der Variable in der Thread-Klasse übermittelst.
Das einzige was Du machst, ist eine Klassenvariable per Konstruktor zu initialisieren und das war's...
Oder hast Du eventuell eine Methode verschwiegen, die den Zustand von "tagesumsatz" übermittelt?
Gruß,
Pawnee -
Dazu musst du wissen, dass Java kein Call-by-Reference unterstützt, das heißt es wird lediglich eine Kopie übermittelt.
Du könntest zwar statt boolean Boolean verwenden, wobei dann der Zeiger übergeben wird (auch wenn man in Java nicht mit Zeigern arbeitet arbeitet Java intern damit), allerdings ist Boolean und dessen boolean Attribut final, dass heißt du kannst den zZustand nicht ändern, ohne ein neues Objekt zu erzeugen, womit sich der Wert im Thread auch nicht ändert. Einzige Alternative ist halt per Event das im Thread zu ändern. -
Da ich das Problem vorhin nicht gelöst bekommen habe, habe ich die Variable direkt im Thread über ein Setter in einem event gesetzt.
Hab immer gedacht, dass sich das genauso verhält, wie wenn man ein Objekt übergibt (siehe bsp. weiter unten). Wusste nicht, dass von der Variable keine Referenz gemacht wird. Hab angenommen, dass das wegen dem Thread so eigenartig ist.
Bei einer final Variable macht der also automatisch eine Kopie. Das ist schon mal gut zu wissen :)
Aber meine Variable ist doch nicht final, oder doch O_O? Liegt es daran, wie ich Boolean/boolean schreibe? Dachte das ist das Selbe.
Bsp. mit Referenz auf Objekt:
public class GUIComponents { private boolean tagesumsatz; public void getTu(){ return tagesumsatz: } ... public void autoRefreshTableStart(Shell shell) { autorefresh = new AutoRefreshStockData(shell, this, ...); autorefresh.start(); } .. public class AutoRefreshStockData extends Thread { private boolean tagesumsatz; ... public AutoRefreshStockData(Shell shell, GUIComponents guico, ...) { this.tagesumsatz = guico.getTu(); ... }
Edit: Ein Moment, man kann doch in Java keine Referenzen einer Variable auf eine andere machen . Das klappt nur mit Objekten. Jetzt weiß ich was pawnee meint^^.
Das einzige was Du machst, ist eine Klassenvariable per Konstruktor zu initialisieren und das war's.
Beitrag zuletzt geändert: 18.11.2010 20:46:16 von cglabs -
Ja genau und das mit final bezieht sich auf die Wrapperklassen. Zum Beispiel Float. Deren Variablen sind final das heißt der Wert lässt sich nicht ändern. Wenn du also Float übergibst, dann hat zwar die Funktion bzw. der Thread eine Referenz, aber sobald du diese manipulierst wird automatisch ein neues Objekt erstellt, dass heißt die alte Referenz zeigt immernoch auf die alte Zahl und nicht auf die neue.
main() { Float f1 = 2f; // einfache Zuweisung Float f2 = f1; // sowohl f1 als auch f2 zeigen auf dasselbe Objekt, bzw. sind dasselbe Objekt Float f2 = 3f; // f1 zeigt weiterhin auf das Objekt mit 2.0 aber f2 zeigt jetzt auf ein neues Objekt mit 3.0
Manchmal ist es Segen manchmal Fluch, dass Java keine gute Möglichkeit bietet, um Call by Reference einzusetzen.
Es ist wie mit dem unsigned, was angeblich absichtlich ausgelassen wurde, aber in alten Docs findet sich der Hinweis, dass es bis jetzt nicht eingebaut wurde mit dem Zusatz, dass es vllt nie eingebaut wird. Es ist also wahrscheinlich mehr eine Sache der fehlenden Motivation/Nachfrage gewesen. -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage