It may be good to do tasks.remove(taskId) here too in case the task thread had never started and so we never got to the "finally" in its run() method.