2015-07-20 22 views
6

Ho 3 oggetti FutureTask<T>. Voglio che vengano elaborati in modo asincrono. Tuttavia, non appena uno dei metodi get() di FutureTasks non restituisce null, desidero continuare i.e il mio metodo (wrapper) restituisce e non attende finché non vengono elaborati gli altri due FutureTasks. ho pensato a qualcosa di simile:Continua quando si prevede un risultato futuro

private File wrapper(final File file) { 
    ExecutorService executors = Executors.newCachedThreadPool(); 
    File returnFile; 
    FutureTask<File> normal= ... 
    FutureTask<File> medium=...  
    FutureTask<File> huge=... 

    executors.execute(normal); 
    executors.execute(medium); 
    executors.execute(huge); 
    try { 
     if((returnFile=normal.get()) != null || 
      (returnFile=medium.get()) != null || 
      (returnFile=huge.get()) != null) 

      return returnFile; 

    } catch(ExecutionException | InterruptedException e) { } 
} 

Non sono sicuro di come catturare le eccezioni (generata dalla get()) in modo corretto, perché presumo che saranno gettati da quando ho appena ritorno senza aspettare gli altri due compiti da completare. Inoltre ho dubbi sul fatto che il codice funzioni come previsto. Sento che sono vicino alla soluzione ma mi manca qualcosa.

+0

usi java 8? – John

+0

attualmente java 7 – Brenne

+0

cosy ecco che si potrebbe avere risultato immediatamente disponibile per l'attività enorme, ma si è inutilmente bloccato in attesa di attività a lunga esecuzione normale. Se capisco correttamente il tuo requisito, è sufficiente che solo uno di questi termini per l'elaborazione. – John

risposta

1

Posso suggerire di verificare FutureTask :: isDone?

sarebbe qualcosa come questo allora:

while(true) { 
    if (normal.isDone()) { 
     return normal.get(); 
    } 
    if (medium.isDone()) { 
     return medium.get(); 
    } 
    if (huge.isDone()) { 
     return huge.get(); 
    } 
} 

EDIT: Si potrebbe cancel gli altri compiti, non appena si dispone di uno dei risultati a portata di mano.

Utilizzando FutureTask::get non è ciò che cercate in quanto sarebbe molto probabilmente tornare sempre il risultato di normal.get() in quanto la documentazione afferma già che:

Waits, se necessario, per il calcolo per completare, e quindi recupera il suo risultato.

Per chiarire quanto sopra: Se si utilizza FutureTask :: ottenere il primo FutureTask si chiama ottenere su molto probabilmente blocco ed attendere fino a quando il risultato è disponibile a tornare.

EDIT2:

Wrap quel ciclo in una nuova Runnable, eseguito dal ExecutorService, passando il primo risultato a disposizione un altro metodo o implementare una richiamata e non c'è più occupato attesa.

+0

Occupato aspettare? Che capolavoro di elaborazione parallela! – Val

+1

Non era mia intenzione promuovere un'attiva attesa. Ho appena provato a mostrare il problema con FutureTask :: get. :) Comunque, grazie per averlo indicato! –

+0

Si prega di aggiungere un collegamento per annullare la documentazione del metodo http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/FutureTask.html#cancel%28boolean%29 –