2010-02-16 5 views
11

Con riferimento al pacchetto java.util.concurrent e all'interfaccia Future, noto (a meno che non mi sbaglio) la possibilità di avviare una lunga attività ed essere in grado di eseguire una query sul i progressi vengono solo con la classe di implementazione SwingWorker.possibilità di ottenere i progressi su un futuro <T> oggetto

Questo pone la seguente domanda:

C'è un modo, in un non-GUI, un'applicazione non-Swing (imaging un'applicazione console) per avviare un lavoro lungo in background e consentono agli altri thread di ispezionare il progresso ? Mi sembra che non ci sia ragione per cui questa capacità debba essere limitata alle applicazioni swing/GUI. Altrimenti, l'unica opzione disponibile, per come la vedo io, è passare attraverso ExecutorService :: submit che restituisce un oggetto Future. Tuttavia, l'interfaccia base di Future non consente il monitoraggio dell'avanzamento.

+2

Vedere http://stackoverflow.com/questions/2003354/how-can-i-report-progress-from-a-background-task – Mark

risposta

5

Ovviamente, l'oggetto Future sarebbe utile solo per bloccare e quindi ricevere il risultato.

L'oggetto Runnable o Callable inviato deve sapere come fornire questo avanzamento (percentuale completa, conteggio dei tentativi, stato (enum?) Ecc. E fornire tale come una chiamata API all'oggetto stesso, oppure pubblicato in alcune risorse di ricerca (nella mappa di memoria o nel database se necessario). Per semplicità tendo ad apprezzare l'oggetto stesso, specialmente dal momento che probabilmente avrete bisogno di un handle (id) per cercare l'oggetto o un riferimento all'oggetto stesso.

Ciò significa che sono operativi 3 thread. 1 per il lavoro effettivo, 1 che è bloccato durante l'attesa del risultato e 1 che è un thread di monitoraggio. L'ultimo potrebbe essere condiviso in base alle tue esigenze.

1

Speravo che esistesse un modo standard di concorrenza per rimanere aggiornati sullo stato di avanzamento di un'attività di lunga durata senza che il programma client si preoccupasse di orchestrare e sincronizzare tutto correttamente. Mi è sembrato che si potesse immaginare una versione estesa dell'interfaccia Future<T> che avrebbe supportato: public short progress(); in aggiunta ai soliti metodi isDone() e get(). Ovviamente l'attuazione del progress() avrebbe quindi bisogno di interrogare l'oggetto direttamente in modo forse Future<T> avrebbe bisogno di essere specificato come Future<T extends CanReportProgress> dove CanReportProgress è la seguente interfaccia:

public interface CanReportProgress { 
    public short progress(); 
} 

Ciò solleva la questione del perché si dovrebbe preoccuparsi di andare attraverso l'oggetto Future anziché chiamare l'oggetto stesso per ottenere il progresso. Non lo so. Dovrò pensarci più. Si potrebbe argomentare che è più vicino al contratto/semantica corrente per cui l'oggetto Callable non è, di per sé, richiamato di nuovo dal programmatore client dopo la chiamata a ExecutorService::submit/execute.

+0

Non so nulla del box JDK che ti possa aiutare molto altro che prendere SwingWorker (parte di 1.6 JDK) come esempio di come potrebbe apparire una versione non Swing. Utilizza RunnableFuture e un getProgress() (con notifica evento)).Questo suona come un solido inizio per me, dal momento che è una quantità nota ed è stato in fase di sviluppo/test per anni da menti più grandi. Buona fortuna. – Matt

+3

Nota che T in Future indica la classe del valore restituito. Non è possibile accedere a T fino al completamento dell'attività. Quindi non ha senso fare T estende CanReportProgress. – Anderson

1

Nel mio caso ho passato un HashSet, con gli oggetti da elaborare, come parametro del metodo, che è stato creato come variabile di istanza nella classe chiamante. Quando il metodo asincrono rimuove gli oggetti dopo l'elaborazione, è possibile recuperare la dimensione della mappa rimanente nel metodo di chiamata. La cosa in generale che passa Oggetti per riferimento risolve il problema.

Problemi correlati