Frage

Ich habe eine Swing-Anwendung, die eine Liste von Objekten speichert. Wenn die Benutzer auf eine Schaltfläche klickt,

Ich möchte auf jedes Objekt zwei Operationen in der Liste durchzuführen, und dann, sobald dies abgeschlossen ist, graphische Darstellung der Ergebnisse in einem JPanel. Ich habe versucht, Swingworker, Callable & Runnable die Verarbeitung zu tun, aber egal was ich tue, während die Liste der Verarbeitung (was ein paar Minuten dauern kann, da es IO gebunden ist), wird die GUI gesperrt.

Ich habe das Gefühl, es ist wahrscheinlich die Art, wie ich die Fäden oder etwas bin aufrufen, oder könnte es mit der Grafikfunktion zu tun? Das ist nicht eingefädelt, da es sehr schnell ist.

Ich habe die beiden Verarbeitungsstufen zu tun, um auch so was ist der beste Weg, um die zweite, um sicherzustellen, hat sich auf der ersten gewartet? Ich habe Join verwendet () und dann

while(x.isAlive())  
{  
        Thread.sleep(1000);  
}

, um zu versuchen und sicherzustellen, aber ich mache mir Sorgen, dies auch die Ursache für mein Problem sein könnte.

Ich habe für einige Hinweise überall gesucht, aber da ich nicht ich bin sicher finden kann ich etwas Dummes hier mache.

War es hilfreich?

Lösung

Das Problem ist, Ihre lange laufende Aufgabe, das Thema ist blockiert, der die GUI ansprechbar hält.

Was Sie brauchen, um auf einem anderen Thread die langen Lauf Aufgabe gestellt zu tun.

Einige der üblichen Wege, dies zu tun verwenden Timer oder ein SwingWorker .

Die Java-Tutorials viele Informationen über diese Dinge haben in ihre Lektion in Gleichzeitigkeit.

Um die erste Aufgabe vor dem zweiten beendet stellen Sie sicher, nur setzt sie beide auf dem gleichen Thread. Auf diese Weise werden Sie nicht zu halten zwei verschiedene Threads zeitlich korrekt kümmern.

Hier ist eine Beispielimplementierung eines SwingWorkerFor Ihres Falles:

public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
    private List<Object> list
    public YourClassSwingWorker(List<Object> theOriginalList){
        list = theOriginalList;
    }

    @Override
    public List<Object> doInBackground() {
        // Do the first opperation on the list
        // Do the second opperation on the list

        return list;
    }

    @Override
    public void done() {
        // Update the GUI with the updated list.
    }
}

Um diesen Code zu verwenden, wenn das Ereignis die Liste ändern gebrannt wird, erstellen Sie einen neuen SwingWorker und sagen, es zu starten.

Andere Tipps

Sie kehren nicht den Swing Thread richtig. Ich weiß, Sie verwenden aufrufbar / runnable aber ich vermute, Sie tun es nicht richtig (auch wenn Sie nicht genug Code sicher zu wissen Post haben).

Die Grundstruktur sei:

swingMethod() { // Okay, this is a button callback, we now own the swing thread
    Thread t=new Thread(new ActuallyDoStuff());
    t.start();
}

public class ActuallyDoStuff() implements Runnable {
    public void run() {
        // this is where you actually do the work
    }
}
Das

ist direkt an der Spitze von meinem Kopf, aber ich vermute, dass Sie entweder nicht die Thread.start tun und stattdessen die run-Methode direkt aufrufen, oder Sie etwas anderes in der ersten Methode, die Sperren zu tun it up (wie Thread.Join). Keines dieser würde den Schwung Faden freizugeben. Die erste Methode muss schnell wieder, die run () Methode kann so lange dauern, wie es will.

Wenn Sie eine Thread.Join in dem ersten Verfahren zu tun, dann wird der Faden wieder auf das System nicht zu werden!

Edit: (Zweite bearbeiten tatsächlich) Ich denke, das Problem zu sprechen, die Sie tatsächlich das Gefühl sind - Sie könnten mehr in Bezug auf einem Model / View / Controller-System zu denken. Der Code, den Sie schreiben, ist der Controller (die Ansicht wird allgemein als die Komponenten auf dem Bildschirm sein - Ansicht / Controller sind in der Regel sehr fest gebunden)

.

Wenn Ihr Controller das Ereignis erhält, sollte es die Arbeit aus Ihrem Modell übergeben. Die Aussicht ist dann aus dem Bild heraus. Es ist nicht für das Modell wartet, ist es gerade getan.

Wenn Sie Ihr Modell fertig ist, muss es dann den Controller sagt etwas anderes zu tun. Es tut dies durch eine der Methoden aufrufen. Diese überträgt die Steuerung an die Steuerung zurück und gehen Sie auf Ihre fröhliche Art und Weise. Wenn Sie darüber nachdenken, es auf diese Weise, die Kontrolle zu trennen und es absichtlich vorbei hin und her nicht so sperrig fühlt, und es ist tatsächlich sehr häufig es auf diese Weise zu tun.

Es klingt wie das Problem sein könnte, dass Sie sich auf die Threads warten aus dem Inneren des GUI-Thread zu beenden. Ihr GUI-Thread sollte nicht auf diesen Threads warten, stattdessen sollten Sie die Worker-Threads eine Methode auf dem GUI-Thread aufrufen, die ein Flag setzt. Wenn beide Flags gesetzt sind, dann wissen Sie beide Threads abgeschlossen und Sie können die Grafik tun.

Ich kann nicht wirklich auf das Swing-Threading-Modell sprechen, aber:

  

Ich habe die beiden Verarbeitungsstufen zu tun, um auch so was ist der beste Weg, um die zweite, um sicherzustellen, hat sich auf der ersten gewartet?

Für diese Art von Funktionalität, würde ich vorschlagen, dass Sie zwei Worker-Threads erstellen, und betten Sie einen JMS-Broker. Liefern Arbeit zu den beiden Themen von Nachrichten in Warteschlangen JMS geben, die sie von gelesen. Ihr GUI-Thread ist frei, um die Warteschlangen zu untersuchen, um zu bestimmen, wann die Arbeit geschieht, und den Stand der Dinge in Ihrer Benutzeroberfläche darstellen.

Die Lösung für mein Problem war eine Mischung aus jjnguy und Bill K der Antworten, so vielen Dank für diese Jungs. Ich brauchte Threads innerhalb eines Swingworker wie folgt zu verwenden:

public class Worker extends SwingWorker<Void, Void>   
{  
    private List<Object> list;  
    public YourClassSwingWorker(List<Object> theOriginalList){  
        list = theOriginalList;  
    }

    @Override
    public List<Object> doInBackground() {
        Thread t = new Thread(new ProcessorThread(list));  
        t.start();
    }

    @Override
    public void done() {
        // draw graph on GUI
    }
}  
class ProcessorThread implements Runnable {  
    //do lots of IO stuff  
    Thread t2 = new Thread(new SecondProcess());
    t2.start();  
}

Dies stellte sicher, dass die ganze Arbeit von Arbeitsthreads von der GUI getan wurde, und gewährleistet auch, dass die Swingworker selbst nicht die ganze Arbeit taten, was ein Problem gewesen sein könnte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top