如何设置简单的Spring计划任务

时间:2016-08-31 14:48:48

标签: java spring multithreading spring-mvc

以下是我认为是Spring网站的相关文档:

  

34.2.2使用TaskExecutor        Spring的TaskExecutor实现用作简单的JavaBeans。在下面的示例中,我们定义了一个使用的bean   ThreadPoolTask​​Executor以异步方式打印出一组消息。

import org.springframework.core.task.TaskExecutor;

public class TaskExecutorExample {

  private class MessagePrinterTask implements Runnable {

      private String message;

      public MessagePrinterTask(String message) {
          this.message = message;
      }

      public void run() {
          System.out.println(message);
      }

  }

  private TaskExecutor taskExecutor;

  public TaskExecutorExample(TaskExecutor taskExecutor) {
      this.taskExecutor = taskExecutor;
  }

  public void printMessages() {
      for(int i = 0; i < 25; i++) {
          taskExecutor.execute(new MessagePrinterTask("Message" + i));
      }
  }

}
  

正如您所看到的,您不是从池中检索线程并自行执行,而是将Runnable添加到队列中,TaskExecutor使用其内部规则来确定任务何时执行。

     

要配置TaskExecutor将使用的规则,已经公开了简单的bean属性。

<bean id="taskExecutor"     class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  <property name="corePoolSize" value="5" />
  <property name="maxPoolSize" value="10" />
  <property name="queueCapacity" value="25" />
</bean>

<bean id="taskExecutorExample" class="TaskExecutorExample">
  <constructor-arg ref="taskExecutor" />
</bean>

我最终必须处理一个触发器,因为我想每N小时/分钟做一些事情,但目前我还在盯着这个例子。方法printMessages()如何执行?我没有看到配置中的任何地方或提及它的代码。

顺便提一下,这是文档中的整个小节:&#34; 34.2.2使用TaskExecutor&#34;

2 个答案:

答案 0 :(得分:0)

执行者和春天没有任何幻想。在您发布的示例中,您已经获得了一个使用run方法实现Runnable的bean。在那里,您应该定义执行程序要运行的内容。在你的情况下它是

 public void run() {
      System.out.println(message);
  }

然后你有一个执行者,它将通过

执行这项任务
taskExecutor.execute(new MessagePrinterTask("Message" + i));

如果您想知道在哪里需要调用此行(调用方法),那么它实际上取决于您的应用以及您尝试做什么。在您的示例中,每当您调用printMessages()时,您的任务将在循环中执行25次。

现在您已经提到过触发器以及如何设置它。我的建议如下。为所有要执行的任务创建简单的pojos,实现类似的接口

public interface Poller extends Runnable
{
  Trigger getTrigger();
}

在所有这些类中实现运行任务(要执行的内容)+定义所需的任务触发器的getTrigger方法,然后在配置类中需要注册它们,如

@Configuration
@EnableScheduling
public class Config implements SchedulingConfigurer
{
  //autowire all pollers
  @Autowired
  private List<Poller> pollers;

  @Bean(destroyMethod = "shutdown")
  public Executor taskExecutor() 
  {
    return Executors.newScheduledThreadPool(25);
  }

  @Override
  public void configureTasks(ScheduledTaskRegistrar taskRegistrar)
  {
    taskRegistrar.setScheduler(taskExecutor());

    for(Poller poller : pollers)
    {
      //register the task and trigger for it to be executed
      taskRegistrar.addTriggerTask(poller, poller.getTrigger());
    }
  }  

}

这应该会自动开始使用所需的触发器执行所有任务。我希望这是有道理的。

答案 1 :(得分:0)

以下配置bean中的方法,使用XML配置根据CRON字符串计划运行。

我们需要:

  1. 一个任务bean,它指定一个实例化并运行的类,
  2. 一个触发器bean,用于指定运行的频率和步骤1中的任务bean,
  3. 一个石英豆,按照触发器的时间表触发步骤2中的触发器。
  4. 以下是像我这样的配置,放在'applicationContext.xml'中:

    在应用程序的'applicationContext.xml'中,我放了以下bean:

    <!-- this task is one that runs periodically, with the period specified elsewhere -->
    <!-- it refreshes data that doesn't change often -->
    <bean id="myRefreshTask" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" value="com.mycompany.myRefreshTask"/>
    </bean>
    
    <!-- this trigger specifies a task and a cron string for a period on which that task runs -->
    <bean id="myRefreshTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail" ref="myRefreshTask"/>
        <property name="cronExpression" value="0 0/1 * 1/1 * ? *"/> <!-- for example testing, every minute -->
        <!--<property name="cronExpression" value="0 30 6 1/1 * ? *"/>--> <!-- for production, every day 6:30am -->
    </bean>
    
    <!-- this is a list of triggers for quartz to fire at their specified intervals -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="myRefreshTrigger"/>
            </list>
        </property>
    </bean>
    

    然后类MyRefreshTask编写如下:

    package mycompany;
    public class MyRefreshTask extends QuartzJobBean {
        @Override
        public void executeInternal(JobExecutionContext context) throws JobExecutionException {
            log.info("MyRefreshTask executing" );
        }
    }
    

    这每分钟在(一个)日志文件中生成一行。我很想知道如何预测哪个日志文件最终会包含Tomcat应用程序不同部分的System.out输出,但那是另一天。