Search code examples
javamultithreadingscheduledexecutorservice

How not to start ScheduledExecutorService task if previous one is not finished


My problem is we have to give it a fixed schedule time to make it start task. Lets say i give 10 seconds and my task has average finish time of 10-15 seconds. Thus after some time waiting threads in quque causes huge memory consumption. If i use syncronized for the method above problem will occur. If i don't use syncronized then i am wasting resources ( cpu) because i dont need to run task if not finished. So i thought a solution of recursive call of task but i believe recursive threads will add more memory problems... what should i do? Shortly i just want to be able to call a task when it is finished. Not fixed time.

public void myScheduledTask{
    doJob(); ( use countdown latch to control waiting if necessary)
    TimeUnit.SECONDS.sleep(x);
    new Thread( new Runnable( { mySchedulTask();   } ));
    or
    executor.execute( a thread that call myScheduledTask() method);
}

Solution

  • The option that sounds like what you're trying to accomplish:

    ScheduledExecutorService executor = Executors.newScheduledThreadPool(count);
    ScheduledFuture<?> future = executor.scheduleWithFixedDelay(
                                       task, 
                                       delay, 
                                       delay, 
                                       TimeUnit.MILLISECONDS
                                      );
    

    This would start your task and execute it after delay milliseconds after the previous completion. Count should be the number of threads you want to use, 1 is acceptable. This also lets you stop the task using the future.

    The problems with your example. a) You are sleeping on an executor thread. Dont do this let the executor handle it. If you were using a threadpool of 1 then this executor couldn't do any work while you're waiting. b) Starting a new thread is taking control from the executor... just use the executor, then you have some control over the execution.

    If you really wanted to stick with the form you have.

    class RecurringTask implements Runnable{
        @Override
        public void run(){
            doJob();
            executor.schedule(this, delay, TimeUnit.MILLISECONDS); 
        }
    }
    

    Now you will be creating Futures that you never use, so it will be harder to control the execution of the task.