Progettazione di un servizio di polling asincrono in Java

3

Attualmente sto scrivendo un bridge Java su una libreria di eyetracking scritta in C. L'intera cosa funziona molto bene, ma costruire un'applicazione reale con esso è difficile, dal momento che l'eyetracking viene eseguito tramite il polling di nuovi dati.

Il polling diventa un problema non appena si dispone di un'interfaccia utente grafica, poiché un loop di polling blocca il ciclo dell'evento principale, bloccando il gui. Ciò inoltre rende impossibile interrompere il ciclo di polling tramite l'input dell'utente.

Il mio obiettivo è creare un servizio di polling abbastanza generico da poter essere utilizzato per molte applicazioni diverse. Deve essere asincrono e deve avere una sorta di meccanismo di callback per utilizzare qualsiasi dato rilevante.

Questa è la mia idea (pseudocodice):

PollService {
  // The filterFunction decides if a eyetracking event is relevant or can be ignored
  setFilterFunction(filterFunction);

  // The callbackFunction is executed if a relevant eyetracking event is polled
  setCallbackFunction(callbackFunction);

  start();
  stop();
}

Il PollService stesso gestisce solo il processo di polling asincrono. Sono fornite un paio di funzioni per eseguire i due passaggi fondamentali:

  1. Filtra se un evento di eyetracking è rilevante, salta l'evento se non
  2. Esegui un tipo di operazione su qualsiasi evento pertinente

Possibili operazioni di callback potrebbero essere:

  • Esegui un calcolo a lungo termine con i dati dell'evento eyetracking
  • Stampa qualcosa sullo schermo
  • Salva qualcosa in un database
  • Comunicare l'evento a un altro thread (utilizzando una coda di messaggi, ad esempio)
  • Aggiorna una GUI (utilizzando Platform.runLater() ad esempio)

Il filterFunction e il callbackFunction sarebbero implementati come interfacce funzionali, quindi gli utenti di Java 8 possono facilmente fornire queste funzioni usando lambdas o riferimenti al metodo.

Cosa ne pensi di questo design? Ci sono evidenti difetti che non vedo?

    
posta Luca Fülbier 04.02.2017 - 11:13
fonte

1 risposta

3

Sembra che il tipo di lavoro flussi reattivi siano fatti per.

Ho usato solo RxJava quindi lo userò per i miei commenti qui, ma ci sono altre implementazioni.

Il tuo servizio di sondaggio suona come un editore o un soggetto che emette eventi quando c'è qualcosa di disponibile nel canale degli eventi. Vuoi trasmettere quegli eventi a tutti gli abbonati interessati.

Non è chiaro nei tuoi requisiti se vuoi trasmettere l'evento indipendentemente dal fatto che tu abbia o meno abbonati (la distinzione tra hot & cold osservabili)

Ci sono alcuni aspetti del design che sarebbero relativamente facili da implementare con questo modello:

Ad esempio, gli oggetti interessati devono solo iscriversi al flusso di eventi:

eventService.getEventStream()
  .subscribe(event -> {
      //handle your event here
   });

Potresti facilmente filtrare a quali eventi il tuo abbonato è effettivamente interessato:

eventService.getEventStream()
  .filter(event -> isAnEventICareAbout(event))
  .subscribe(event -> {
      //handle only events you care about here
   });

Puoi facilmente controllare i thread e assicurarti che i calcoli degli eventi avvengano in un thread diverso da quello del loop di eventi dell'interfaccia utente.

eventService.getEventStream()
  .filter(event -> isAnEventICareAbout(event))
  .observeOn(Schedulers.io())
  .subscribe(event -> {
      //handle your event in an io thread here
   });

Potresti facilmente avvolgere il tuo loop di eventi dell'interfaccia utente in un altro flusso di eventi e assicurarti che tutti gli eventi che elabora avvengano solo all'interno del loop di eventi dell'interfaccia utente.

PublishingSubject<Event> subject = Platform.getUIEventSubject().observeOn(eventLoop());
subject.onNext(new UIEvent()); //event handling occurs in eventloop 

Puoi controllare facilmente gli abbonamenti degli ascoltatori di eventi interessati. Quando un ascoltatore non è più interessato a ricevere eventi, può annullare l'iscrizione e quando non ci sono abbonati, il servizio di polling può automaticamente interrompere la produzione e riprendere quando arrivano nuovi abbonati.

    Subscription subs = eventService.getEventStream()
      .subscribe(event -> {
          //handle your event here
       });

   //later, no longer interested
   subs.unsubscribe();
   subs = null

Il servizio di polling potrebbe determinare quando non ci sono più iscrizioni e interrompere il polling e riprendere quando arriva un nuovo abbonamento. Puoi anche controllare / evitare la creazione di nuovi poller per abbonato e utilizzare un polling globale per tutti i sottoscrittori (ad es. Publish.refCount ()), ecc. Ecc.

In generale, il problema che stai cercando di risolvere sembra un buon adattamento per la programmazione reattiva e ha questo stile di programmazione funzionale che cerchi.

Puoi prendere in considerazione di dare un'occhiata al libro Programmazione reattiva con RxJava che ritengo sia ottimo e penso che sarebbe di grande aiuto se decidessi di seguire questo approccio.

    
risposta data 04.02.2017 - 16:37
fonte

Leggi altre domande sui tag