Make SparkListener interface asynchronous, and fix UI bugs

In addition to making the SparkListener interface asynchronous, this request fixes 4 bugs in the UI:

One bug caused the UI to crash if you try to look at a job's status
before any of the tasks have finished.

The second bug was a concurrency issue where two different threads
(the scheduling thread and a UI thread) could be reading/updating
the data structures in JobProgressListener concurrently (SPARK-810).

The third bug mis-used an Option, also causing the UI to crash
under certain conditions.

The 4th bug allowed web UI users to add entries in the JobProgressListener's hash maps that would never be deleted if they went to a page for a stage that didn't exist (thus causing a memory leak, albeit at small scale).