简体   繁体   中英

Specify order of execution of task while using single threaded executor

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

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.

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
  }
}

Here is something of a weird solution. Provided you have a default executor.

ExecutorService service = Executors.newSingleThreadExecutor();

Your need to keep track of how many a tasks have completed and how many need to be completed.

AtomicInteger a = new AtomicInteger(0);
int totalA = 10;

Then for submitting a task.

void submitTask(Runnable t){
    Runnable r = ()->{
        if( t instance of TaskA ){
            try{
                t.run();
            } finally{
                a.incrementAndGet();
            }
        } else if( t instance of TaskB ){
            if( a.get() >= totalA ){
                t.run();
            } else{
                service.submit(this);
            }
        } else{
            throw new RuntimeException("not an acceptable task!");
        }

    }
    service.submit(r);
}

This will filter the TaskA's and the TaskB's, TaskA's will be immediately executed, but TaskB's will be resubmitted.

There are some flaws to this design. I think ThreadPoolExecutor can be setup a little better where you reject a task if it is not ready to be run.

I suspect that you could design your setup a little better. They have tools like an ExecutionCompletionService, or CountDownLatch that are made for creating barriers to execution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM