command: Implement LongCommandId using AtomicLong

Avoid blocking on unique command ID generation.
schedule: Add IO context managers

TreeIoContext is the general case, allowing the API user to self-manage
dependencies between IO jobs. LinearIoContext manages the dependencies
for the API user, where each submitted job will depend on the previous
submission.

The API exposed through the Scheduler interface asks that an IO object
be passed to generate the appropriate context with. It's intended that
this be the OutputStreamWriter or BufferedWriter that submitted IO jobs
will be manipulating. The context manager then handles synchronization
on the IO object, ensuring correctness and removing clutter from job
implementations that would otherwise have to perform the synchronization
manually.