Home > Enterprise >  Specify order of execution of task while using single threaded executor
Specify order of execution of task while using single threaded executor

Time:09-14

I currently have a bunch of tasks that I want to execute. I am using the single-threaded executor in java. These are mainly of 2 types. Let's call these types TaskA and TaskB. I have 10 tasks of type TaskA and 5 tasks of type TaskB. I have to execute them all but I cannot control the sequence in which they are submitted to the executor. A few tasks of type TaskB might be submitted to the executor before all 10 tasks of type TaskA have been submitted. Is there any way to ensure that all 10 tasks of type TaskA are executed before the 5 tasks of type TaskB? In order to successfully execute all tasks of type TaskB, I need to first execute all tasks of type TaskA. You may think of TaskA tasks to be responsible for data loading and TaskB tasks for data processing. Without loading the data I cannot process it and run into exceptions

Please do let me know if I can phrase the question better if it is unclear

CodePudding user response:

No, the default executor service implementations do not differentiate between submitted tasks.

You need a task manager object.

Define a class that contains the single-threaded executor service as a member field. That class offers methods submit( TaskA ta ) and submit( TaskB tb ).

The second method collects the B tasks, as a queue, holding them for now if we’ve not yet processed ten A tasks.

The first method accepts each A task, submitting to the executor service immediately. And the first method counts those submissions. On the tenth A task, flag is set, and all stored B tasks are submitted to the member field executor service.

The second method always checks for that “A tasks done” flag being set. If set, any further B tasks submissions are sent directly to the executor service.

Your task manager class could itself implement the ExecutorService interface. But I don’t know if I would go that far.

CodePudding user response:

The way I think you could do this is using the semaphore/locking pattern.

first, you need a lock. You can use an object

Object lock = new Object();

Then you need a count of how many A tasks have completed.

int completedAs = 0; // variable name is completed 'A's, not 'as'

Both of these should be static or otherwise available to TaskA and TaskB. Then what you can do is only add the TaskB's to the ExecutorService when the appropriate number of TaskA's have completed, like

for (TaskB : allTaskBs) {
  synchronized(lock) {
    //add the taskB to the ExecutorService
  }
}

And then upon taskA completion:

synchronized(lock) {
  completedAs  ;
  if (...) {
    lock.notify(); // you can call this multiple times to release multiple B's
  }
}
  • Related