0

I have some tasks which we need to execute again and again in a defined interval for each task, and each task has to execute in their own different different thread.

Example: let's say I have task1,task2,task3,task4.....taskN

I want to execute each task again and again in defined intervals
e.g.

  • task1 interval after each 1 sec
  • task2,4 sec
  • task3,2 sec
  • ....
  • taskN in 10 sec

and for each task different different thread should be created not in for loop kind of,

Please suggest the approach and share the sample java code, or let say I has 10 database queries and all queries has to run in different threads and after defined interval again and again till infinite..

wassgren
  • 18,651
  • 6
  • 63
  • 77
Sachin Singh
  • 739
  • 4
  • 12
  • 29

3 Answers3

4

A simple solution would be to make use of Java's ScheduledExecutorService and use the scheduleAtFixedRate method.

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

Here is a simple example that demonstrates how the delays work:

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));
    }

}

Example output (for 1 run). Your results should be similar but might not be the exact same. Each task is first executed after the initialDelay in the provided unit, and then are scheduled to occur after each 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
mkobit
  • 43,979
  • 12
  • 156
  • 150
  • This won't get independent thread per tasks. Based on any available thread, if any of the tasks is supposed to get executed, it will be taken by a random free thread. – piyushGoyal Feb 04 '19 at 09:02
2

For the scheduling I recomend Quartz. You can setup tasksthat will run on their own thread.

Example, create a StatefulJob implementation:

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
        }
    }
}

Initialize the scheduler:

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

Create a method for scheduling:

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);

}

Note the CronScheduleBuilder.cronSchedule("0/"+seconds+" * * * * ?") part. You can have more information on the scheduling syntax here.

After that, you have a method to use like this:

scheduleQuery( "QRY1", 3 ); //RunQueryJob class will run in a new thread every 3 seconds passing "QRY1" in the DataMap.

Netto
  • 284
  • 2
  • 10
1

You could use the Executor Service provided by java.util.concurrent. This

may help.

ramp
  • 1,256
  • 8
  • 14