java中的多线程任务调度程序

时间:2015-01-08 06:40:24

标签: java multithreading concurrency task scheduler

我有一些任务需要在每个任务的定义间隔内反复执行,每个任务必须在各自不同的线程中执行。

示例:假设我有 task1,task2,task3,task4 ..... taskN

我想在定义的时间间隔内一次又一次地执行每项任务 例如

  • 每1秒后的任务1间隔
  • task2,4 sec
  • task3,2 sec
  • ....
  • 任务N在10秒内

并且对于每个任务,应该创建不同的不同线程,而不是for循环类型,

请建议方法并分享示例java代码,或者说我有10个数据库查询,并且所有查询都必须在不同的线程中运行,并且在定义的间隔后一次又一次地直到无限...

3 个答案:

答案 0 :(得分:3)

一个简单的解决方案是使用Java的ScheduledExecutorService并使用scheduleAtFixedRate方法。

ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                          long initialDelay,
                                          long delay,
                                          TimeUnit unit)

Creates and executes a periodic action that becomes enabled first after the given initial
delay, and subsequently with the given delay between the termination of one execution
and the commencement of the next. If any execution of the task encounters an exception, 
subsequent executions are suppressed. Otherwise, the task will only terminate
via cancellation or termination of the executor.

Parameters:
  command - the task to execute
  initialDelay - the time to delay first execution
  delay - the delay between the termination of one execution 
          and the commencement of the next
  unit - the time unit of the initialDelay and delay parameters

这是一个简单的例子,演示了延迟的工作原理:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Example {

    private static long START_TIME;

    public static void main(String[] args) throws InterruptedException {

        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(4);

        START_TIME = System.currentTimeMillis();
        Runnable task1 = printTask("T1");
        Runnable task2 = printTask("T2");
        Runnable task3 = printTask("T3");
        Runnable task4 = printTask("T4");

        scheduledExecutorService.scheduleAtFixedRate(task1, 3, 3, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(task2, 5, 3, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(task3, 0, 5, TimeUnit.SECONDS);
        scheduledExecutorService.scheduleAtFixedRate(task4, 2, 2, TimeUnit.SECONDS);

        Thread.sleep(15000);
        scheduledExecutorService.shutdown();
        scheduledExecutorService.awaitTermination(6000, TimeUnit.SECONDS);
    }

    private static Runnable printTask(String prefix) {
        return () -> System.out.println(prefix + ": " + (System.currentTimeMillis() - START_TIME));
    }

}

示例输出(1次运行)。您的结果应该相似,但可能不完全相同。每个任务首先在提供的initialDelay中的unit之后执行,然后安排在每个delay之后执行:

T3: 38
T4: 2039
T1: 3039
T4: 4040
T2: 5040
T3: 5040
T1: 6039
T4: 6040
T2: 8040
T4: 8040
T1: 9039
T3: 10040
T4: 10040
T2: 11040
T1: 12039
T4: 12040
T2: 14039
T4: 14039

答案 1 :(得分:2)

对于我的建议,我建议Quartz。 您可以设置将在自己的线程上运行的tasks

示例,创建一个StatefulJob实现:

class RunQueryJob implements StatefulJob {
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        try {
            String query = (String) jec.getMergedJobDataMap().get("query");
            //run query
        } catch (Exception ex) {
            //Handle Exception
        }
    }
}

初始化调度程序:

Scheduler scheduler;
scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();

创建一个安排方法:

public void scheduleQuery( String query, int seconds ){
   JobDataMap map =new JobDataMap();
   map.put("query", query);

   JobDetail job = JobBuilder.newJob(RunQueryJob.class)
                    .usingJobData( map ).
                    build();

   Trigger trigger = TriggerBuilder
        .newTrigger()
        .withSchedule(
            CronScheduleBuilder.cronSchedule("0/"+seconds+" * * * * ?"))
        .build();

   scheduler.scheduleJob(job, trigger);

}

请注意CronScheduleBuilder.cronSchedule("0/"+seconds+" * * * * ?")部分。您可以在scheduling syntax here上获得更多信息。

之后,你有一个方法可以这样使用:

scheduleQuery(&#34; QRY1&#34;,3); // RunQueryJob类将每隔3秒在一个新线程中运行&#34; QRY1&#34;在DataMap中。

答案 2 :(得分:1)

您可以使用java.util.concurrent提供的Executor服务。 This

可能会有所帮助。