o Async que fez teu sistema ficar um lixo (ReactiveX)

Tu usa ReactiveX / RXJAVA? então o conhecimento dessa Thread pode te fazer um pouco mais Senior.

Vamos imaginar que o teu sistema tem varias tasks, como por exemplo:

  • buscar algo no servidor
  • escrever em um arquivo de config
  • combinar eventos vindo do usuário com stream de dados

Se tu usa RXJAVA pra fazer isso de forma async, continue lendo, do contrário talvez esse conhecimento possa explodir a tua cabeça... enfim, tu está executando as tasks de forma async e isso é ótimo só que agora tu precisa escolher uma Scheduler.

Por padrão o RXJAVA vai executar na Thread que chamou subscribe() e dependendo de onde tu tá subscrevendo isso pode acontecer na thread principal ou em uma thread qualquer de um ThreadPool.

Scheduler.Computation: vai ter um ThreadPool (FixedSchedulerPool) que começa com ZERO threads e criará threads até a quantidade de núcleos disponíveis. E esse limite de threads pode ser ótimo para executar tasks de forma rápida na CPU e depois liberar para o GC.

Mas NUNCA utilize computation scheduler para operaçōes de IO (leitura e escrita de arquivos, banco de dados, network, socket...) pois essas tasks possuem tempo indefinido de execução e tu pode fazer lock da Thread, bloqueando assim outras tasks que estejam esperando por uma thread do ThreadPool.

E NUNCA utilize Completable.never() já que o dispose nunca acontecerá, a task pode acabar mas a subscription vai se manter ativa.

Scheduler.IO: tem um ThreadPool que mantem um Cache de threads em Idle por 60 segundos, esse ThreadPool vai escalar para quantas threads o sistema conseguir disponibilizar e vai reutilizar threads em Idle antes de descartar elas. Isso parece ótimo certo? Porque não usar IO para tudo?

Utilizar Scheduler.IO para tasks que não fazem IO como por exemplo um debounce um defer um calculo simples um map vai fazer com que threads sejam criadas e mantidas em Idle por 60 segundos de forma desnecessária. Isso significa que o GC vai precisar trabalhar mais de forma tardia, o tradeoff aqui de não bloquear outras tasks pela quantidade de nucleo é a memória e o overload de manter as threads.

Em casos raros como o que me fez escrever essa Thread tu vai precisar criar um Scheduler customizado e para isso tu pode usar um Executer Service.

Exemplo:

val executor = Executors.newCachedThreadPool(threadFactory)
return Schedulers.from(executor)