Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does spring task scheduler wait for previous task to finish?

Tags:

java

spring

I have the following task scheduler setup:

<bean id="Task" class="foo.bar.Task" />

<bean id="TaskScheduler"
  class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
    <property name="waitForTasksToCompleteOnShutdown" value="true" />
    <property name="poolSize" value="1000" />
</bean>

<task:scheduled-tasks scheduler="TaskScheduler">
  <task:scheduled ref="Task" method="run" cron="*/5 * * * * *" />
</task:scheduled-tasks>

The Task just prints a line and sleeps for 10 seconds. With this setup, my expectation was that the task would run every 5 seconds, regardless of whether the previous task had finished it's execution (ie stopped sleeping). But that's not the case, the task runs once ever 15 seconds (the sleep time and then the next time the cron is hit).

How can I configure this so that the task runs every 5 seconds regardless of whether the previous execution finished?

like image 605
GuerillaNerd Avatar asked Nov 02 '12 15:11

GuerillaNerd


People also ask

How can spring overlap schedules be prevented?

by default, spring uses a single-threaded Executor. so no two @Scheduled tasks will ever overlap. even two @Scheduled methods in completely unrelated classes will not overlap simply because there is only a single thread to execute all @Scheduled tasks.

What is fixed delay in spring scheduler?

Schedule a Task at Fixed Delay In this case, the duration between the end of the last execution and the start of the next execution is fixed. The task always waits until the previous one is finished. This option should be used when it's mandatory that the previous execution is completed before running again.

How does a spring scheduler work?

Java Cron ExpressionThe @EnableScheduling annotation is used to enable the scheduler for your application. This annotation should be added into the main Spring Boot application class file. The @Scheduled annotation is used to trigger the scheduler for a specific time period.

What is ThreadPoolTaskScheduler?

ThreadPoolTaskScheduler ThreadPoolTaskScheduler is well suited for internal thread management, as it delegates tasks to the ScheduledExecutorService and implements the TaskExecutor interface – so that single instance of it is able to handle asynchronous potential executions as well as the @Scheduled annotation.


1 Answers

In you run method put @Async anotation and see

   @Async
   public void run{

   }

or you can

Try out this

<bean id="schedulerTask"
       class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
    <property name="mytaskClass" ref="mytaskClass" />
    <property name="targetMethod" value="fooMethod" />
</bean>

<bean id="mytaskClass" class="foo.bar.Task" />

<bean id="timerTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
    <property name="timerTask" ref="schedulerTask" />
    <property name="delay" value="10" />
    <property name="period" value="5000" />
</bean>

<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
    <property name="scheduledTimerTasks">
        <list>
            <ref local="timerTask" />
        </list>
    </property>
</bean>

Then Your class

 package foo.bar;

 public class Task{

  public void fooMethod(){
  // do task
 }

}

Added as per the request

   <!-- Thread pool related configurations  -->
   <bean name="workerThread" class="foo.WorkerThread"/>

  <bean name="managerThread" class="foo.ManagerThread" >
     <constructor-arg type="org.springframework.core.task.TaskExecutor" ref="taskExecutor" />
     <constructor-arg type="foo.process.WorkerThread" ref="workerThread"/>
   </bean>

   <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
 <property name="corePoolSize" value="5" />
 <property name="maxPoolSize" value="30" />
 <property name="queueCapacity" value="100" />
</bean>
<!-- End Thread pool related configurations  -->

ManagerThread.java

public class ManagerThread {

private  TaskExecutor taskExecutor=null;
private  WorkerThread workerThread=null;


/**
 * @param taskExecutor
 * @param workerThread
 */
public ManagerThread(final TaskExecutor taskExecutor,final WorkerThread workerThread) {

    this.taskExecutor = taskExecutor;
    this.workerThread = workerThread;
}  


/**
 * Create a new thread and execte the requests
 * @param parameter
 */
 public synchronized void  fire(final Object parameter) {
    taskExecutor.execute( new Runnable() {
         public void run() {
             workerThread.execute( parameter );
         }
    });
  }

WorkerThread.java

@Component
public class WorkerThread {




public void execute(final Object request) {

     // do the job
    }

}

You could customize this as per your requirement

like image 129
someone Avatar answered Sep 19 '22 15:09

someone