0

Suppose I have a few tasks to run in parallel in Java. Each task returns either success or failure. Each task has an associated deadline. If a task does not finish by the deadline it is interrupted (all tasks are interruptable) and returns failure.

If one of the tasks fails (i.e. return failure) we interrupt all other tasks, which are still running.

We should wait till all tasks finish and finally return either success if all tasks return success or failure if at least one task returns failure.

How would you implement it? I am going to use util.concurrent. Which library primitives would you suggest?

Michael
  • 41,026
  • 70
  • 193
  • 341
  • This sounds quite similar to `ExecutorService.invokeAll`, except that that has a single timeout for all the tasks rather than independent timeouts for each sub-task. – Ian Roberts Apr 09 '13 at 10:19
  • @IanRoberts I am afraid I really need independent timeouts for each task. – Michael Apr 09 '13 at 10:26

2 Answers2

1

I would use ExecutorService with CountDownLatch and a array list of Future interface to hold the tasks:

List<List<String>> elements = MyPartition.partition(bigObjectList, size); 
List<Future<?>> tasks = new ArrayList<Future<?>>();
ExecutorService executor = Executors.newFixedThreadPool(4);
CountDownLatch doneSignal =  new CountDownLatch(10);
for(List<String> l: elements) {         
   ReadTask worker = new ReadTask(doneSignal, l);
   tasks.add(executor.submit(worker));
}   

long timeout = 10000;
doneSignal.await(timeout, TimeUnit.MINUTES);
boolean notFinished = false;
if(doneSignal.getCount() > 0) {
  for(Future<?> fut : tasks) {
    if(!fut.isDone()) {
      System.out.println("Sub Thread " + fut + " has not finshed!");
      fut.cancel(true);             
      notFinished = true;
    }
  }
}
sk2212
  • 1,688
  • 4
  • 23
  • 43
1

ExecutorCompletionService seems closest

    ExecutorService ex = Executors.newCachedThreadPool();
    ExecutorCompletionService<Boolean> cs = new ExecutorCompletionService<Boolean>(
            ex);
    List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
       ... add tasks
    List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>();
    for (Callable<Boolean> t : tasks) {
        futures.add(cs.submit(t));
    }
    for (!futures.isEmpty()) {
        try {
            Future<Boolean> f = cs.poll(1, TimeUnit.SECONDS);
            futures.remove(f);  // poll returns the same instance of Future as in the futures list
            if (f == null || !f.get()) {  // poll returns null on timeout
                break;
            }
        } catch (Exception e) {
            break;
        }
    }
    // cancel remaining tasks, if all finished OK the list will be empty
    for (Future<Boolean> future : futures) {
        future.cancel(true);
    }
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275