Optimize Thread Pools

* Optimize number of threads in pool based on available processors
* Kill core threads when not in use (android-8+)
* com.parse.Executors#newCachedThreadPool works the way you'd want it to
    * Reuses threads in pool if available
    * Creates more threads until core pool size
    * Queues threads until queue size
    * Creates more threads until max pool size
    * Rejects
* Add Task#UI_THREAD_EXECUTOR to continue work on the UI thread.