Search code examples
javaconcurrencyjava.util.concurrent

How to run concurrent job with dependent tasks?


I have a situation that I need to work on

I have a class which has send method, example

@Singleton
class SendReport {

 public void send() {}
}

The send method is called from a user click on web page, and must return immediately, but must start a sequence of tasks that will take time

send
 ->|
   | |-> Task1
 <-|      |
        <-|
          | 
        |-> Task2 (can only start when Task1 completes/throws exception)
        <-|
          | 
        |-> Task3 (can only start when Task2 completes/throws exception)
        <-|

I am new to Java concurrent world and was reading about it. As per my understanding, I need a Executor Service and submit() a job(Task1) to process and get the Future back to continue.

Am I correct?

The difficult part for me to understand and design is
- How and where to handle exceptions by any such task?
- As far as I see, do I have to do something like?

    ExecutorService executorService = Executors.newFixedThreadPool(1);
    Future futureTask1 = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("doing Task1");
        return "Task1 Result";
    }
    });
    if (futureTask1.get() != null) {
    Future futureTask2 = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("doing Task2");
        return "Task2 Result";
    }
    }
    ... and so on for Task 3

Is it correct? if yes, is there a better recommended way?

Thanks


Solution

  • If you just have a line of tasks that need to be called on completion of the previous one than as stated and discussed in the previous answers I don't think you need multiple threads at all.

    If you have a pool of tasks and some of them needs to know the outcome of another task while others don't care you can then come up with a dependent callable implementation.

    public class DependentCallable implements Callable {
    
    private final String name;
    private final Future pre;
    
    public DependentCallable(String name, Future pre) {
        this.name = name;
        this.pre = pre;
    }
    
    @Override
    public Object call() throws Exception {
        if (pre != null) {
            pre.get();
            //pre.get(10, TimeUnit.SECONDS);
        }
        System.out.println(name);
        return name;
    }
    

    A few other things you need to take care of based on the code in your question, get rid of future.gets in between submits as stated in previous replies. Use a thread pool size of which is at least greater than the depth of dependencies between callables.