Reputation: 1
I have a Task object with a one-to-many relationship to the sub task object. Both objects have status fields. The status of the sub task in a task object can be updated simultaneously in concurrent threads. At the end of the update of a sub task, the status of the other sub task under the same task object is checked. If all are completed, the status of the task is marked as completed. The update on the database happens after exiting the sub task update method.
public void updateSubTask(SubTask subTask, Status status) {
subTask.setStatus(status);
//check all subtask status
if (Status.Completed.equals(status) {
boolean allCompleted = true;
for(SubTask otherTask : subTask.getParentTask().getSubTasks()){
if (!otherTask.equals(subTask) && !Status.Completed.equals(otherTask.getStatus)) {
allCompleted = false;
break;
}
}
if (allCompleted) {
updateParentTask(subTask.getParentTask(), Status.Completed);
}
}
}
Let's say there are two sub tasks under Task A, call it sub task 1 and sub task 2.
1. The update method is called by Thread A for sub task 1.
2. The update method is called by Thread B for sub task 2.
3. Thread A updates sub task 1 to "completed" and checks status of sub task 2
4. Thread B updates sub task 2 to "completed" and checks status of sub task 1
5. Both threads A and B see the sub tasks 2 and 1 respectively as "not completed", therefore they exit the method without updating Task A to "completed"
I now end up with Task A that is not yet completed but all sub tasks are completed.
As an interim solution, I am using a singleton object containing a hashmap. Every time a thread starts processing a sub task, the hashmap is checked first if it contains the Task ID of the sub task's main task. If yes. I put that thread to sleep for a few seconds and try checking again. If it is not in the hashmap, then that ID is placed in the hashmap and processing proceeds. After processing, the ID is removed from the hashmap.
This works OK at the moment but using the Thread.sleep method does not seem to be an elegant way to suspend a thread. Synchronized blocks is not an option here because I should still allow other threads to update other sub tasks given that these sub tasks are under a different main task.
Is there something I could use in the java.concurrent library (or any other library for that matter) that has a "lock and key" mechanism similar to what I have described?
Upvotes: 0
Views: 106
Reputation: 140613
Simple answer: observer pattern; probably based on ye good old PropertyChangeListener.
It should neither be responsibility of a "subtask" to worry about the status of its "parent" task nor the status of other "subtasks".
The canonical answer to that is that the "parent" task needs to "listen" what is going on within its children.
Upvotes: 1
Reputation: 406
In my opinion your design is sub-optimal.
What I would do, is to make the Task to watch for events in the Subtasks (listening for task completion).
What you need is to synchronize two async sub-tasks. So that synchronization should happen in the Task. You can use an AtomicInteger (or even a boolean) to know when you are done with the two subtask.
So task job would be to
Upvotes: 0