Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use ScheduledExecutorService with ExecutorCompletionService?

I'm trying to use ExecutorCompletionService and ScheduledExecutorService together.

What I need to do is schedule disparate activities that each have "delays before execution" and then "reschedule them" (which different delays) based upon the result of the last run."

The problem that I have is that I cannot use ExcecutorCompletionService submit with a "delay"

I tried the following, but it blocks forever...

Obviously I'm missing a fundamental issue in the Java Language.

Is there anyway to schedule tasks to the ScheduledExecutorService such that the CompletionService "knows about it"?

public class Bar {

    private ScheduledExecutorService scheduledExecutor;
    private Future<Status> action1Future;
    private Future<Status> action2Future;
    private ExecutorCompletionService<Status> pool;
    private long delay1 = 10;
    private long delay2 = 20;
    private long delay3 = 30;

    public void start() {
        scheduledExecutor = Executors.newScheduledThreadPool(3);

        Action1 a1 = new ActionOne(); // Action1 implements Callable<Status>
        Action2 a2 = new ActionTwo(); // Action2 implements Callable<Status>

        pool = new ExecutorCompletionService<Status>(scheduledExecutor);
        action1Future = scheduledExecutor.schedule(a1, delay1, TimeUnit.SECONDS);
        action2Future = scheduledExecutor.schedule(a2, delay1, TimeUnit.SECONDS);
        monitorAndRestart();
    }

    private void monitorAndRestart() {
         boolean isDone=false;
        do {
        try {
            // THIS IS WHERE IT BLOCKS.
            Future<Status> processedItem = pool.get();
            if (processedItem == action1Future) {
                if (processedItem.get() == Status.GOOD) {
                    action1Future = scheduledExecutor.schedule(new ActionOne(), delay1, TimeUnit.SECONDS);
                } else {
                    action1Future = scheduledExecutor.schedule(new ActionOne(), delay2, TimeUnit.SECONDS);
                }
            } else if (processedItem == action2Future) {
                if (processedItem.get() == Status.GOOD) {
                    action1Future = scheduledExecutor.schedule(new ActionOne(), delay2, TimeUnit.SECONDS);
                } else {
                    action1Future = scheduledExecutor.schedule(new ActionOne(), delay3, TimeUnit.SECONDS);
                }
            }
        } catch (InterruptedException e) {
            isDone = true;
            // handle this.. shudown whatever
        }
        catch (ExecutionException e) {
            // handle this
        }
      } while (isDone == false);
    }

    public static void main(String[] args) {
        Bar myRunner = new Bar();
        myRunner.start();
    }
}

If I put the "delay in the Callable" create the callable via new ActionOne(delay); and use CompletionService.submit(..) It works.

actionFuture1 = pool.submit(new ActionOne(delay1));
/////


public class ActionOne implements Callable<Status>(
   private final delay;
   public ActionOne(long dl) {
       delay=dl;
   }
   Status call() {
       try {
         Thread.sleep(delay * 1000); // seconds
          return doSomething()
       } catch (...) { //thread.sleep execptions}
   }
 }

So I guess the final question is the following: Is there something fundamentally better about ScheduledExecutorService over the Thread.sleep(delay) way of doing this?

like image 828
JalapenoGremlin Avatar asked Nov 10 '22 07:11

JalapenoGremlin


1 Answers

We do this sort of rescheduling in one of our apps, and we settled on wrapping the Task like Ed Thomas suggested. (We also made the rescheduling super flexible by passing an iterator that returns the next execution time for the task - allows us to use many different scheduling strategies).

Another option is to subclass ScheduledThreadPoolExecutor and override afterExecute. This may ultimately be cleaner than wrapping the Task.

like image 144
Kevin Day Avatar answered Nov 15 '22 07:11

Kevin Day