2009-09-10 12 views
6

Ho una serie di attività simultanee da eseguire. Se uno di loro fallisce, voglio interromperli tutti e attendere la fine. Ma supponendo che nessuno di loro fallisca, voglio aspettare che tutti finiscano.In Java, come posso attendere tutte le attività, ma interrompere il primo errore?

ExecutorCompletionService sembra quasi quello che voglio qui, ma non sembra essere un modo per dire se tutte le mie attività sono state fatte, tranne mantenendo un conteggio separato del numero di attività. (Si noti che entrambi gli esempi di Javadoc per ExecutorCompletionService tengono traccia del conteggio "n" delle attività, e lo usano per determinare se il servizio è finito.)

Sto trascurando qualcosa, o davvero? devo scrivere questo codice da solo?

risposta

2

Sì, è necessario tenere traccia se si sta utilizzando un ExecutorCompletionService. In genere, si dovrebbe chiamare get() sul futuro per vedere se si è verificato un errore. Senza scorrere le attività, in che altro modo si potrebbe dire che uno è fallito?

+0

Potrebbe gestire la condizione di errore nell'attività, ma sì, chiamare get() sul futuro è la cosa migliore. –

+0

Ovviamente ho bisogno di iterare sui compiti, ma posso solo prendere() i future da ExecutorCompletionService. (Questo è ciò che fa l'esempio Javadoc.) Il problema è che non posso semplicemente accettare() finché non esaurisco i compiti, perché se prendo() quando non c'è lavoro, rimarrò bloccato per sempre. –

+1

Giusto, quindi è necessario precalcolare il numero di attività (come si pensava), e prenderlo molte volte. –

1

Se la serie di attività è di una dimensione nota, è necessario utilizzare il secondo esempio in javadoc.

Tuttavia, se non si conosce il numero di attività che si invierà al servizio di completamento, si avrà una sorta di problema produttore-consumatore. Un thread sta producendo compiti e inserendoli nell'ECS, un altro sta consumando i future sull'attività tramite take(). Si potrebbe utilizzare un semaforo condiviso, consentendo al produttore di chiamare release() e al consumer di chiamare acquire(). La semantica di completamento dipenderebbe dalla vostra applicazione, ma un booleano volatile o atomico sul produttore per indicare che è fatto sarebbe sufficiente.

Suggerisco un semaforo di attesa/notifica con sondaggio() perché c'è un ritardo non deterministico tra il tempo di produzione di un'attività e il tempo in cui il futuro di tale attività è disponibile per il consumo. Pertanto, il consumatore e il produttore devono essere solo leggermente più intelligenti.

+0

In realtà, nel mio caso, ho solo un thread principale che produce i compiti e consuma i futures. Posso certamente avere quel filo che tiene traccia deterministica del numero di compiti, ma mi sembra strano che io debba farlo. –

Problemi correlati