Patricia Shanahan wrote:
I have questions about the TaskManager remove(Task) method. Trying to
end work by any means other than run to completion is always a bit
tricky.
In the event of a remove call for an active Task, TaskManager issues
an interrupt unless the call is in the task's thread. It also removes
the Task from its bookkeeping.
In the current implementation, removal from the ArrayList immediately
stops the removed task from blocking later tasks that need to runAfter
it. That can let a dependent task start running before the removed
task notices the interrupt. That could be bad if, for example, they
share data that is being protected through the runAfter system.
Perhaps a hashmap might be used to store tasks that are pending removal,
so they can be left on the queue until the removed task has been
interrupted?
It will get worse in any performance improved TaskManager. One of the
performance issues is a tendency to use only one thread, regardless of
the number of runnable tasks or the constructor parameters, if there
are a lot of runAfter dependencies. I plan to fix that so that the
number of threads will be in accordance with the constructor parameters.
The other issue is that a task that ignores the interrupt can keep
possession of its thread, indefinitely, despite a remove call. Since
we only create a bounded number of threads, that could effectively
kill the TaskManager. To what extent are TaskManager instances shared
by tasks whose run methods don't have the same trust characteristics?
Currently TaskManager is only used internally, so the trust should be
the same between tasks, although I like the idea of a singleton
TaskManager and did mention it earlier, that doesn't suit the current
implementation. We could put an AccessController permission check in
TaskManager before a task is placed into the queue?
Patricia