IO is the most often used Scheduler. It can be created by calling Subscribers.io(), and it is perfect for (as the name implies) IO-related workloads, such as network requests, accessing the file system, or content resolvers on Android.
The IO Scheduler is backed by a worker (wrapper for a thread) pool. Initially, the pool starts with one worker, and it is reused between different Observables when available. However, if there are no workers left in the pool, a new worker is created. After the worker finishes its current execution, it becomes available once again for the next execution; so, the system can save resources by reusing workers (threads) instead of recreating them each time.
The size of a pool is unbounded, so care must be taken when there is a chance that an unbounded (or a very large) amount of Observables will be created. However, the unused workers are removed after 60 seconds so that the pool size can shrink down after a while.
In general, it is a very handy and robust Scheduler, so it can be used in almost all cases where IO operations are involved.