2

How can I create a timeout for each command that is running in parallel using java.​util.​concurrent.ExecutorService?

My code is something like this:
For example in the code below I need obj1 run for maximum 1 min, and obj2 for 2 mins and others 5 mins.

ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(obj1);
exService.execute(obj2);
exService.execute(obj3);
exService.execute(obj4);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);
if (finshed) {
    //Doing something
}

EDIT:
Unfortunately the class of obj1 - obj4 is scraping some web pages using WebHarvest that uses jakarta HttpClient for reading web pages and HttpClient (And neither WebHarvest itself) doesn't have any feature for timeout on entire page reading and/or scraping job.
This is my time consuming task and I thought about killing ExecutorService thread after a timeout to handle this problem.

Ariyan
  • 14,760
  • 31
  • 112
  • 175
  • 1
    This should answer your question: http://stackoverflow.com/questions/2758612/executorservice-that-interrupts-tasks-after-a-timeout – Ionel Gog Jan 06 '12 at 12:33
  • That solution depends on `Thread#interrupt()`. Depending on what the tasks are doing, that may have no real effect as the interrupt mechanism works only with certain blocking operations; it is not a general `Thread#stop` replacement. See http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html – Ramon Jan 06 '12 at 12:44
  • @Ramon: I added some details at the end of my question, please take a look at them. Thanks – Ariyan Jan 06 '12 at 13:04
  • In that case you might want to try the solution with `Thread#interrupt()`. Otherwise, it depends on the details of the library you're using. Perhaps you could replace the OutputStream where your downloads go with an OutputStream subclass that throws an exception when `write` is called after the timeout has been reached. – Ramon Jan 06 '12 at 13:55

3 Answers3

3

In general, there is no reliable way to make a separate thread quit. In particular, there is no reliable way to interrupt and stop your task after a timeout from outside that task. What you need to do is make the tasks themselves responsible for stopping after their time runs out. Depending on what they do, you might be able to abstract this behaviour into a superclass something like:

public abstract class TimeoutRunnable implements Runnable {
   private final long timeLimitMillis;
   private long startTimeMillis;

   public TimeoutRunnable(long timeLimitMillis) {
      this.timeLimitMillis = timeLimitMillis;
   }

   public final void run() {
      startTimeMillis = System.currentTimeMillis();
      while (System.currentTimeMillis() - startTimeMillis < timeLimitMillis) {
         runIteration();
      }
   }

   protected abstract void runIteration();
}

Then in your subclass override, runIteration() and perform a single "step" of the task.

Ramon
  • 8,202
  • 4
  • 33
  • 41
1

The only reasonably reliable way to kill a task is to run it in a separate process and kill that process if it times out. Using any other approach with a library which does not support timeouts is likely to be error prone at best.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
1

from my point of view I think that such stuff requires some more robust foundations than plain Java standard classes , that 's why I would suggest to use any scheduler infrastructure (Quartz or any other project) which may gives you handles (job identifiers) to kill your time consuming tasks .

You may have something like this :

Main Thread launches the Quartz Scheduler , receive subscriptions from different jobs saying : Job1,Job 2 and TimeCheckerJob

TimeCheckerJob would be a forever job ,notified to any new job and would check for living time for each any new job... In this job you would have to deal with start time of each job, beware of the OS clocks and don't try to setup too hard constraints (nanoseconds is pure fiction).

HTH My 2 cents Jerome

romje
  • 650
  • 3
  • 4