Domanda

Ho un'applicazione di oscillazione che memorizza un elenco di oggetti. Quando gli utenti fa clic su un pulsante,

Voglio eseguire due operazioni su ogni oggetto nella lista, e poi una volta che è completo, grafico i risultati in un JPanel. Ho cercato SwingWorker, richiamabile & Runnable per fare l'elaborazione, ma non importa quello che faccio, durante l'elaborazione della lista (che può richiedere fino a un paio di minuti, in quanto è legato IO), l'interfaccia grafica è bloccato.

Ho la sensazione è probabilmente il modo in cui sto chiamando i fili o qualcosa del genere, o potrebbe essere a che fare con la rappresentazione grafica delle funzioni? Questo non è avvitato in quanto è molto veloce.

che devo fare le due fasi di lavorazione al fine troppo, quindi qual è il modo migliore per garantire la seconda ha atteso il primo? Ho usato join (), e quindi

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

per cercare di garantire questo, ma sono preoccupato che questo potrebbe essere la causa del mio problema troppo.

Ho cercato dappertutto per alcuni indicatori, ma dal momento che non riesco a trovare alcuna Sono sicuro che sto facendo qualcosa di stupido qui.

È stato utile?

Soluzione

Il problema è, il vostro compito lungo in esecuzione sta bloccando il filo che mantiene l'interfaccia grafica reattivo.

Quello che è necessario fare è mettere il compito lungo in esecuzione su un altro thread.

Alcuni modi comuni di farlo utilizzano i timer o un SwingWorker .

Il tutorial Java hanno un sacco di informazioni per quanto riguarda queste cose in la loro lezione di concorrenza.

Per assicurarsi che il primo compito finisce prima del secondo, appena li sia messi sullo stesso thread. In questo modo non dovrà preoccuparsi di mantenere due fili diversi cronometrati correttamente.

Ecco un esempio di implementazione di un SwingWorkerFor vostro caso:

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

Per utilizzare questo codice, quando l'evento per modificare l'elenco è sparato, creare un nuovo SwingWorker e dirgli di iniziare.

Altri suggerimenti

Non si restituisce il filo oscillazione correttamente. Mi rendo conto che si sta utilizzando callable / eseguibile ma credo non si sta facendo bene (anche se non è stato sufficiente inviare il codice per sapere con certezza).

La struttura di base potrebbe essere:

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

Questa è solo la parte superiore della mia testa, ma credo che si sia non stanno facendo il Thread.start e sono invece chiamando direttamente il metodo di esecuzione, o si sta facendo qualcos'altro nel primo metodo che si blocca l'alto (come Thread.join). Nessuno di questi sarebbe liberare il filo oscillazione. Il primo metodo deve restituire rapidamente, il metodo run () può prendere il tempo che vuole.

Se si sta facendo un Thread.join nel primo metodo, poi il filo è non essere restituito al sistema!

Modifica: (Seconda modifica in realtà) Penso di parlare con il problema che si sta in realtà sente - si potrebbe desiderare di pensare di più in termini di un modello di sistema / view / controller. Il codice che si sta scrivendo è il controller (la vista è generalmente considerato essere i componenti sullo schermo - vista / regolatore sono di solito molto strettamente legato)

.

Quando il controllore ottiene l'evento, si dovrebbe passare il lavoro fuori per il vostro modello. La vista è quindi fuori dal quadro. Non attende per il modello, è solo fatto.

Quando il modello è finito, deve poi dire il controller per fare qualcosa di diverso. Lo fa attraverso uno dei metodi Invoke. Questo trasferisce il controllo al controller e si va sul vostro modo allegro. Se si pensa in questo modo, la separazione di controllo e deliberatamente passare avanti e indietro non si sente così ingombrante, ed è in realtà molto comune a farlo in questo modo.

Sembra che il problema potrebbe essere che si è in attesa sui fili per finire dall'interno del filo GUI. Il tuo filo GUI non deve aspettare in queste discussioni, invece si dovrebbe avere i thread di lavoro invocano qualche metodo sul thread GUI che imposta un flag. Quando entrambe le bandiere sono impostati poi si sa entrambi i fili finito e si può fare il grafico.

Non posso davvero parlare con il modello di threading swing, ma:

  

che devo fare le due fasi di lavorazione al fine troppo, quindi qual è il modo migliore per garantire la seconda ha atteso il primo?

Per questo tipo di funzionalità, io suggerirei di creare due thread di lavoro, e incorporare un broker JMS. Fornire lavoro ai due fili passando messaggi nelle code JMS che leggere. Il vostro filo GUI è allo scopo di esaminare le code per determinare quando il lavoro sta accadendo e rappresentare lo stato del gioco nella vostra interfaccia utente.

La soluzione al mio problema era un misto di jjnguy e le risposte di Bill K, quindi grazie molto per questo ragazzi. Avevo bisogno di utilizzare i thread all'interno di uno SwingWorker in questo modo:

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();  
}

Questo fatto in modo che tutto il lavoro è stato svolto dai thread di lavoro lontano dalla GUI, e anche garantire che lo SwingWorker in sé non stava facendo tutto il lavoro, che avrebbe potuto essere un problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top