Ciao, 2018-03-29 16:19 GMT+02:00 Federico Fissore [email protected] [it-torino-java-jug] <[email protected]>: > Ciao a tutti > > l'altro giorno stavo chattando con un collega su CompletableFuture e > AsyncResponse di jax.rs. Lui, fan di spring, mi risponde che per rendere > una API REST asincrona ti basta scrivere una cosa come > > @RequestMapping(value = "/callable", method = RequestMethod.GET) > public Callable<String> executeSlowTask() { > Callable<String> callable = taskService.execute(); > > return callable; > } > > Cioè wrappa in un Callable tutto il codice sincrono e sequenziale che > hai, punto. > > L'approccio non mi ha convinto. Tutte le attività potenzialmente > asyncrone, come le query verso un db o le chiamate http ad altri > servizi, vengono trattate come sincrone e gestite dal thread del thread > pool con cui `taskService` lavora.
Esatto. Nota che se le chiamate HTTP sono fatte con un client non-blocking allora non ti serve un altro thread. Query JDBC verso un DB, non mi risulta che ci siano API non-blocking, quindi è tutto sincrono e ti serve un altro thread. Query non-JDBC verso un DB, se hai della API non-blocking allora non serve un altro thread. > Poi ho pensato che in effetti non ho fatto una scelta migliore quando ho > convertito tutte le API (java) a CompletableFuture, che di default si > basa sul `ForkJoinPool.commonPool()`, di nuovo un unico thread pool > comune a tutti i task. La scelta di usare il common pool dipende solo da te. Puoi sempre usare CompletableFuture.supplyAsync(task, executor). L'executor lo prendi da Spring e è uno tuo. > Quindi qual è il modo migliore per far fare alla CPU altro lavoro mentre > è in attesa del risultato di una query? > Oppure ha ragione il mio collega e potevo risparmiarmi del lavoro? Wrappare tutto in un Callable funziona solo se sai già che è tutto sincrono e che le chiamate sincrone fanno blocking I/O. Se no è uno spreco di risorse. Se sai che chiami delle API non-blocking meglio usare Spring's DeferredResult che il Callable. Con DeferredResult puoi evitare di allocare un thread che invece è sempre allocato con il Callable. Regole: * Se faccio blocking I/O, va bene fare lo spawn di un thread, quindi Callable è la soluzione più semplice. * Se faccio logica sincrona senza I/O, niente Callable e niente threads * Se uso delle API non-blocking, DeferredResult e niente threads. -- Simone Bordet --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
