Java并发&循环任务执行

时间:2014-02-05 16:19:44

标签: java multithreading concurrency timer scheduled-tasks

我的任务包含20个不同的步骤:

public class MyTask implements Runnable {
    @Override
    public void run() {
        // Step #1. Fetch data
        Data data = fetchData();

        // Step #2. Do something with data
        SomeResult result = dataProcessor.process(data);

        // ...

        // Step #19. Generate report
        Report report = reportFactory.newReport(result);

        // Step #20. Clean up
        cleanUp();
    }
}

我想:

  • 在某个时间(应用程序启动)开始运行任务,我们将调用STARTING_POINT
  • Timer开始每分钟一次又一次地运行任务(ScheduledExecutorServiceSTARTING_POINT?)。
  • 如果任务仍在运行(例如,它在步骤#17),当1分钟周期结束时,则中断任务并阻止它继续执行,然后(再次因为我们正在确定一个新周期)每一分钟),重新开始一个新周期(从一开始就再次呼叫run())。
  • 否则,如果任务在1分钟周期结束前完成,那么将STARTING_POINT重置为当前时间(System.currentTimeInMillis()?)并再次开始每分钟循环,但是从新{{1 }}。
  • 一旦这些1分钟的周期开始,它们就不会停止,除非被可能从STARTING_POINT或类似的东西调用的外部“控制”线程中断。

例如,假设该应用启动,ShutdownHook是2/4/2014 11:15:36 EST。假设第1个循环完全 1分钟,以完成执行STARTING_POINT内的所有20个步骤。然后它将在11:15:36到11:16:36之间执行,然后第二个周期将重新开始并调用run()。让我们说这个周期很慢,当我们到达11:17:36时,它只在第11步。它将关闭并停止执行,然后第三个周期将重新开始并调用run()。如果这个周期很快并且在11:17:53之前完成run(),那么run()将成为2/4/2014 11:17:53,并且第4个周期将开始执行并调用再次STARTING_POINT。等

我完全不知道从哪里开始挖掘这个。有任何想法吗?我愿意使用JDK附带的任何东西,以及除Apache Camel之外的任何开源库。

2 个答案:

答案 0 :(得分:1)

看起来Spring Batch会是一个很好的选择。我会推荐它。

您可以使用spring integrated quartz scheduler安排作业。 作业将分为多个步骤(也可以实现并行性)。 乔布斯可以重新开始,最重要的是,你只需要很少的工作。

大多数东西都正确接线。我提供了一个bean配置作为示例。

    <bean id="threadPoolExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <property name="corePoolSize" value="20" />
    <property name="maxPoolSize" value="25" />
    <property name="queueCapacity" value="500" />
</bean>
<bean id="jobLauncher"
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
    <property name="taskExecutor" ref="asyncTaskExecutor" />
</bean>

<batch:job id="batchjob" job-repository="jobRepository">
    <batch:step id="step1" next="step2">
        <batch:tasklet ref="start" />
    </batch:step>
    <batch:step id="step2" next="step3.master">
        <batch:tasklet ref="fetchData" />
    </batch:step>
    <batch:step id="step3.master">
        <batch:partition step="step3.slave"
            partitioner="processingPartitioner">
            <batch:handler grid-size="20" task-executor="threadPoolExecutor" />
        </batch:partition>
    </batch:step>
    <batch:listeners>
        <batch:listener ref="MyListener" />
    </batch:listeners>
</batch:job>

<batch:step id="step3.slave">
    <batch:tasklet ref="processFile" />
</batch:step>

<bean id="myLauncher" class="com.<>.batch.MyLauncher">
    <property name="job" ref="batchJob" />
    <property name="jobLauncher" ref="jobLauncher" />
</bean>

<task:scheduled-tasks>
    <task:scheduled ref="myLauncher" method="launch"
        cron="0 0 0 0 0 1" />
</task:scheduled-tasks>

可以定义每个步骤,并且应该实现Tasklet。弹簧本身提供了一些例子。

答案 1 :(得分:0)

cancel()将取消当前线程。你可以在20种方法中检查每种方法后的时间并致电取消。

time2.scheduleAtFixedRate(new TimerTask() {
        long t0 = System.currentTimeMillis();
        @Override
        public void run() {
          if (System.currentTimeMillis() - t0 ) {
              cancel();
          } else {
              sendSamples();
          }
        }