Quando utilizzare Future vs Listener

3

Ho iniziato a lavorare su un progetto esistente (un sdk) al lavoro, e la base di codice utilizza gli ascoltatori come se non ci fosse un domani. Praticamente ogni secondo metodo richiede una sorta di argomento listener e devo ancora trovare un'occorrenza in cui il listener non è la classe chiamante o una classe anonima dichiarata quando viene chiamato il metodo.

La mia domanda è: quando / perché è appropriato usare Listener su Future < > in questo modo?

// Util methods
static void postSuccess(Listener listener, Object object) {
    Util.runOnUI(() -> { listener.success(object); });
}
static void postError(Listener, Exception ex) {
    Util.runOnUI(() -> { listener.failure(ex); });
}

void foo ( Bar bar, Listener listener ) {
    executor.submit(() -> {
        try {
            // work_on() is a potentially long running function
            Result res = work_on( bar );
            Util.postSuccess(listener, res)
         }
         catch (Exception ex) {
            Util.postError(listener, ex);
         }
     }
}

Nel codice precedente il chiamante non ha alcun controllo su quando viene richiamato il metodo del listener. Il seguente codice consentirebbe al chiamante di decidere se attendere o controllare più tardi e generalmente sembra fornire un maggiore controllo:

Future<Result> foo ( Bar bar ) {
    return executor.submit(() -> { return workOn( bar ) };
}

Mi scuso se mi manca qualcosa di ovvio, sono solo fuori dal college per tre mesi, ma questo codice di ascolto mi fa male.

    
posta Alex Meuer 30.09.2016 - 12:53
fonte

2 risposte

6

Con entrambe le alternative, puoi ottenere la stessa funzionalità: eseguire un lungo pezzo di codice senza bloccare il chiamante e fornire un mezzo per fornire il risultato più tardi.

Ma dalla mia esperienza personale, ho sempre incentivato Future sul callback per i seguenti motivi:

  • Il flusso del programma è molto più difficile da capire con i callback che con Future . Il flusso è come "saltare" rendendo difficile anche il debug.
  • I callback svelano la firma del metodo. Quando guardi void foo(Bar bar, Listener listener) , in primo luogo: restituisce void sebbene ci si sarebbe aspettati che questo metodo restituisse qualcosa in un contesto sincrono. Secondo: l'elenco dei parametri è inquinato con un Listener che non ha nulla a che fare con il dominio (= rumore visivo). D'altra parte, con un Future l'intento è più chiaro: Ho bisogno di un Bar per consegnarti un Result , ma non direttamente, solo in qualche futuro .
  • Puoi finire nel callback hell . Con Future il tuo codice rimane più compositivo ed evolutivo. A proposito, Java 8 viene anche fornito con un'intera nuova API chiamata CompletableFuture che rende l'uso dell'asincronismo più espressivo e si affida a Future .
  • Con i callback, si applica il thread in cui viene chiamato il listener (nel tuo caso il thread dell'interfaccia utente). Ma cosa succede se l'utente non vuole che il callback venga eseguito nel thread dell'interfaccia utente? È troppo tardi perché questa dipendenza è stata codificata in il tuo codice e il chiamante è bloccato. Con Future il chiamante è libero di scegliere il thread in cui vuole gestire il risultato.
  • Le richiamate possono creare un sacco di garbage thread se eseguite con noncuranza perché ogni listener deve essere richiamato in un altro thread (questo, tuttavia, non è il caso dell'esempio poiché si usa sempre il thread dell'interfaccia utente). Con Future è coinvolto solo un thread.
risposta data 30.09.2016 - 14:46
fonte
1

Il listener (come lo si presenta sopra) è più semplice da usare e richiede meno risorse (non richiede un thread). È un modello molto comune.

Puoi certamente usare Future , ma forse suggerirei che in molti casi la semplice richiamata sincrona sia tutto ciò che è richiesto.

È che soffre del problema che normalmente ti aspetti che il metodo di callback venga eseguito immediatamente (altrimenti bloccherai l'esecuzione sul thread principale). Se hai intenzione di fare molto lavoro in un listener, forse lo lascerei cadere in un nuovo thread a quel punto.

    
risposta data 30.09.2016 - 13:50
fonte

Leggi altre domande sui tag