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

Reply via email to