step 3: spin up a thread pool executor, and use futures and callbacks to get the sync work off of the io loop