L'uso di Runnable al di fuori del contesto del multithreading è valido?

6

Ispirato alla domanda SO , vorrei capire meglio il contratto definito da Runnable , insieme a quando è e non è accettabile utilizzare l'interfaccia Runnable . Sappiamo che il caso d'uso più comune di Runnable deve essere implementato da una classe che deve essere eseguita su un thread separato:

Runnable task = () -> {
    // Code to be executed on another thread
};
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(task);

Questo genera due domande:

  1. Questo è l'unico modello accettabile per il suo utilizzo?
  2. In caso contrario, quali sono altri pattern di utilizzo accettabili per Runnable che non ruotano attorno al multithreading?

Il caso d'uso nella domanda SO originale è di creare un modo generico per eseguire codice prima e dopo l'esecuzione di un metodo senza ripetizioni, come ad esempio:

public void example1() {
    before();
    method1();
    after();
}

public void example2() {
    before();
    method2();
    after();
}

La risposta di Eran propone di utilizzare Runnable per consentire l'incapsulamento della logica per ciascun metodo, insieme a un singolo metodo che accetta Runnable come argomento e richiama Runnable#run al momento opportuno:

public void call(Runnable method){
    before();
    method.run();
    after();
}

call( () -> { method1(); });
call( () -> { method2(); });

Tuttavia, l'utilizzo di Runnable in questo modo ha incontrato qualche disaccordo, affermando che questo non è un uso accettabile di Runnable . Questa è una preoccupazione valida o una questione di opinione stilistica?

Dalla mia ricerca, Javadoc per Runnable afferma il seguente contratto, che sembra essere ancora sostenuto con questo utilizzo di Runnable :

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread.

Inoltre, se l'utilizzo al di fuori del contesto del multithreading fosse scoraggiato o non consentito, mi aspetterei che:

  1. Il Javadoc per menzionarlo da qualche parte, o
  2. Runnable per essere in un pacchetto specifico della concorrenza, ad es. java.util.concurrent , tuttavia è disponibile in java.util .
posta nickb 15.12.2015 - 22:10
fonte

3 risposte

6

Anche se è ancora chiaramente una questione di dibattito tra la comunità, Alex ha rivelato un commento lasciato da Brian Goetz , Java Language Architect presso Oracle, che credo sia la risposta canonica definitiva a questa domanda. Ho copiato i suoi commenti qui sotto, enfatizzando il mio:

The EG discussed this in some detail and concluded that it was better to coopt Runnable than to create the opportunity for confusion because there were two competing abstractions. In a perfect world, we might have rewritten the Javadoc to reflect that its use had (long ago) become broader than was imagined in 1995, but the reality is that well before 2014 it became broadly understood that Runnable was the JDK's primary "task" abstraction, regardless of its connection with threads.

    
risposta data 16.12.2015 - 15:35
fonte
4

Stream e lambda espressioni invitano l'uso di interfacce a metodo singolo. È abbastanza facile scrivere una nuova interfaccia, ma anche tentare di ridisegnare semplicemente quello che il sistema fornisce, invece di sporcare il codice base con interfacce minuscole.

Tuttavia, quando un'interfaccia è strongmente associata a qualcosa, rimappare la sua semantica pone le basi per un futuro manutentore del codice per perdere tempo alla ricerca di cose che non ci sono. Nel caso di Runnable, il futuro manutentore potrebbe perdere tempo a cercare la concorrenza elusiva che pensano sia sottilmente incorporata nel codice.

Sebbene sia possibile aggiungere commenti ovunque, sarebbe più semplice creare la propria interfaccia, stabilendo esplicitamente la propria semantica.

    
risposta data 16.12.2015 - 02:09
fonte
0

Direi che l'uso di Runnable al di fuori del contesto del multi-threading sarebbe fuorviante per quanto riguarda l'intento del tuo codice. Certo, puoi usarlo al di fuori di quel contesto perché dopotutto è solo un'interfaccia con un metodo di funzionamento senza arg. Ma potrebbe essere meglio creare la tua interfaccia che è più specifica per quanto riguarda l'intento di ciò che fa il codice.

    
risposta data 16.12.2015 - 02:09
fonte

Leggi altre domande sui tag