PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Java] Threading: Stop/Start geht, Wait friert anderen Thread mit ein?


Funky Bob
2010-03-05, 10:41:30
Hallo Forum,
ich spiele gerade mit Threads rum um mich nen bissl fitter darin zu machen.
Nun habe ich ein Problem:
Ich habe einen WorkerThread erstellt, der einfach nur inkrementiert und jede xte Inkrementierung an die GUI weitergibt (jedes 10.000.000ste Inkrement, damit die GUI nicht einen Preozessor komplett auslastet).

Starten dieses WorkerThreads geht, Stoppen geht auch, keine Probleme.

Nun habe ich noch einen Knopf eingebaut, der ein wait() aufrufen soll.
Erst hatte ich noch das Problem, das ich wohl keinen Monitor auf das Objekt hatte und das wait ist mir um die Ohren geflogen, dies habe ich mit synchronized(x) aber beseitigt.
Nun wird leider der aufrufende GUI-Thread mit schlafen gelegt und ich habe keine Ahnung warum.

Hier der Code:
(Die vermutlich fraglichen Stellen farblich markiert, Grün läuft, Rot friert die GUI mit ein)

public class CustomPanel extends JPanel implements TextPush {
private JLabel infoText;
private JButton startThread;
private JButton stopThread;
private JButton waitThread;
private JComboBox chosenFunction;
private Thread workerThread = null;
public CustomPanel()
{
this.setLayout(new FlowLayout());
this.setMinimumSize(new Dimension(1,1));
String comboBoxItems[] = {"Integrate","Differentiate","Counter"};
chosenFunction = new JComboBox(comboBoxItems);
this.add(chosenFunction);
startThread = new JButton("Start Calculating");
startThread.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent arg0) {
if(workerThread==null)
{
switch(chosenFunction.getSelectedIndex())
{
case 0:
Integrator integrator = new Integrator(new WiredFunction(), CustomPanel.this);
workerThread = new Thread(integrator);
break;
case 1:
Differentiator diff = new Differentiator(new WiredFunction(), CustomPanel.this);
workerThread = new Thread(diff);
break;
case 2:
Counter count = new Counter(CustomPanel.this);
workerThread = new Thread(count);
break;
}
workerThread.start();
} else if(workerThread.getState()==Thread.State.WAITING)
{
synchronized(workerThread) {
workerThread.notifyAll();
}
}
}

});
this.add(startThread);
stopThread = new JButton("Stop Calculating");
stopThread.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0)
{
if(workerThread != null)
{
workerThread.stop();
workerThread = null;
CustomPanel.this.setInfoText("Stopped Calculations");
}
}
});

this.add(stopThread);
waitThread = new JButton("Thread wait");
waitThread.addActionListener(new ActionListener() {
@Override
public synchronized void actionPerformed(ActionEvent arg0)
{
Thread.currentThread();
if(workerThread!=null)
synchronized(workerThread) {
try {
workerThread.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
this.add(waitThread);
infoText = new JLabel("Status: Wait\nChoose Action and Start calculating");
this.add(infoText);
}
public synchronized void setInfoText(String text)
{
this.infoText.setText(text);
}
}


Danke für die Hilfe!

Edit2:
Das Thread.currentThread() im roten Teil ist nur zum Debuggen drinne, woltle schauen ob das auch wirklich nen anderer Thread ist oder ob da sonstwas schief läuft...

Sindri
2010-03-05, 14:51:42
War es nicht so das bei wait() immer der Thread schlafen gelegt wird der gerade aktiv ist?
Also wenn du im Main-Thread bist kannst du auch ThreadXY.wait() schreiben, aber es wird trotzdem der Main-Thread warten.

Btw sagst du nicht jetzt das workerThread warten soll bis workerThread Bescheid gibt das er fertig ist?

Tiamat
2010-03-05, 16:39:05
Wer wait sagt, muss auch notify sagen ^^. Das heißt, nur wait() führt dazu, dass alle anderen Threads, die auf diese Methode zugreifen wollen, in die Warteschleife gelegt werden und es keine Meldung darüber gibt, dass diese die Warteschleife verlassen können und das trifft in deinem Fall den EventThread von AWT bzw. Swing.
Deswegen muss bevor die Methode verlassen wird, was noch angefügt werden ? :-)

Gast
2010-03-14, 10:12:10
ausm javadoc von Object (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html)

"wait()
Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object."

Übersetzt und im Kontext:
workerThread.wait() legt den GUI Thread so lange schlafen bis jemand workerThread.notify() oder notifyAll() aufruft. Was mit nem schlafenden GUI Thread als Usereingabe ziemlich unmöglich sein dürfte :)

Ich kann dir "Java Concurrency in Practice" empfehlen. Da steht der Threadkrams sehr einfach erklärt drin. Vielleicht hat ja deine Uni-, Schul-, oder Stadtbibliothek ein Exemplar davon.

Funky Bob
2010-03-15, 16:39:06
ausm javadoc von Object (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html)

"wait()
Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object."

Übersetzt und im Kontext:
workerThread.wait() legt den GUI Thread so lange schlafen bis jemand workerThread.notify() oder notifyAll() aufruft. Was mit nem schlafenden GUI Thread als Usereingabe ziemlich unmöglich sein dürfte :)

Ich kann dir "Java Concurrency in Practice" empfehlen. Da steht der Threadkrams sehr einfach erklärt drin. Vielleicht hat ja deine Uni-, Schul-, oder Stadtbibliothek ein Exemplar davon.

Sorry das ich mich jetzt erst melde...
Aber wieso friert der GUI-Thread ein wenn ich auf einen anderen Thread (also workerThread) mit .wait() zugreife? Rein logisch wäre es doch so, das dann auch der workerThread schlafen geht?!

PatkIllA
2010-03-15, 21:46:57
Der Thread in dem die Methode aufgerufen wird wartet halt auf eine Benachrichtigung.
Es ist in deinem Fall jetzt vielleicht etwas verwirrend, dass das Objekt auf dem du wait aufrufst auch ein Thread ist, aber das hat damit nicht zu tun.

Funky Bob
2010-03-16, 17:41:40
Der Thread in dem die Methode aufgerufen wird wartet halt auf eine Benachrichtigung.
Es ist in deinem Fall jetzt vielleicht etwas verwirrend, dass das Objekt auf dem du wait aufrufst auch ein Thread ist, aber das hat damit nicht zu tun.


Also müsste ich mir in meinem WorkerThread quasi ne Methode schreiben die selbst wait für sich aufruft, damit der Thread sich schlafen legt, richtig?

PatkIllA
2010-03-16, 21:19:36
Auf welchem Objekt du wait aufrufst ist mehr oder minder egal. Es ist wichtig aus welchem Thread das gemacht wird.