Wednesday, October 30, 2013

Java ScheduledThreadPoolExecutor Example to schedule tasks after delay and execute periodically

Sometimes we need to execute a task periodically or after specific delay. Java provides Timer Classthrough which we can achieve this but sometimes we need to run similar tasks in parallel where creating multiple Timer objects will be an overhead to the system and we would like to have a thread pool of scheduled tasks.
Java provides scheduled thread pool implementation through ScheduledThreadPoolExecutor class that implements ScheduledExecutorService interface that defines the contract methods to schedule a task with different options.
Sometime back I wrote a post about Java ThreadPoolExecutor where I was using Executors class to create the thread pool. Executors class also provide factory methods to create ScheduledThreadPoolExecutor where we can specify the number of threads in the pool.
Let’s say we have a simple Runnable class like below.
package com.journaldev.threads;

import java.util.Date;

public class WorkerThread implements Runnable{

private String command;
    
    public WorkerThread(String s){
        this.command=s;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+" Start. Time = "+new Date());
        processCommand();
        System.out.println(Thread.currentThread().getName()+" End. Time = "+new Date());
    }

    private void processCommand() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString(){
        return this.command;
    }
}
It’s a simple Runnable class that takes around 5 seconds to execute its task.
Let’s see a simple example where we will schedule the worker thread to execute after 10 seconds delay.
package com.journaldev.threads;

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


public class ScheduledThreadPool {

 public static void main(String[] args) throws InterruptedException {
  ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
  
  
  //schedule to run after sometime
  System.out.println("Current Time = "+new Date());
  for(int i=0; i<3 10="" add="" all="" by="" delay="" do="" finish="" for="" heavy="" i="" inished="" let="" pre="" processing="" scheduledthreadpool.isterminated="" scheduledthreadpool.schedule="" scheduledthreadpool.shutdown="" scheduler="" some="" spawn="" system.out.println="" tasks="" thread.sleep="" threads="" timeunit.seconds="" to="" wait="" while="" worker="" workerthread="">
When we run above program, we get following output that confirms that tasks are running with 10 seconds delay.
Current Time = Tue Oct 29 15:10:03 IST 2013
pool-1-thread-1 Start. Time = Tue Oct 29 15:10:14 IST 2013
pool-1-thread-2 Start. Time = Tue Oct 29 15:10:15 IST 2013
pool-1-thread-3 Start. Time = Tue Oct 29 15:10:16 IST 2013
pool-1-thread-1 End. Time = Tue Oct 29 15:10:19 IST 2013
pool-1-thread-2 End. Time = Tue Oct 29 15:10:20 IST 2013
pool-1-thread-3 End. Time = Tue Oct 29 15:10:21 IST 2013
Finished all threads
Note that all the schedule() methods return instance of ScheduledFuture that we can use to get the thread state information and delay time for the thread. ScheduledFuture extends Future interface, read more about them at Java Callable Future Example.
There are two more methods in ScheduledExecutorService that provide option to schedule a task to run periodically.

scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)

We can use this method to schedule a task to run after initial delay and then with the given period. The time period is from the start of the first thread in the pool, so if you are specifying period as 1 second and your thread runs for 5 second, then the next thread will start executing as soon as the first worker thread finishes it’s execution.
For example, if we have code like this:
  for (int i = 0; i < 3; i++) {
   Thread.sleep(1000);
   WorkerThread worker = new WorkerThread("do heavy processing");
   // schedule task to execute at fixed rate
   scheduledThreadPool.scheduleAtFixedRate(worker, 0, 10,
     TimeUnit.SECONDS);
  }
Then we will get output like below.
Current Time = Tue Oct 29 16:10:00 IST 2013
pool-1-thread-1 Start. Time = Tue Oct 29 16:10:01 IST 2013
pool-1-thread-2 Start. Time = Tue Oct 29 16:10:02 IST 2013
pool-1-thread-3 Start. Time = Tue Oct 29 16:10:03 IST 2013
pool-1-thread-1 End. Time = Tue Oct 29 16:10:06 IST 2013
pool-1-thread-2 End. Time = Tue Oct 29 16:10:07 IST 2013
pool-1-thread-3 End. Time = Tue Oct 29 16:10:08 IST 2013
pool-1-thread-1 Start. Time = Tue Oct 29 16:10:11 IST 2013
pool-1-thread-4 Start. Time = Tue Oct 29 16:10:12 IST 2013

scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit)

This method can be used to start the periodic execution with initial delay and then execute with given delay. The delay time is from the time thread finishes it’s execution. So if we have code like below:
  for (int i = 0; i < 3; i++) {
   Thread.sleep(1000);
   WorkerThread worker = new WorkerThread("do heavy processing");
   scheduledThreadPool.scheduleWithFixedDelay(worker, 0, 1,
     TimeUnit.SECONDS);
  }
Then we will get output like below.
Current Time = Tue Oct 29 16:14:13 IST 2013
pool-1-thread-1 Start. Time = Tue Oct 29 16:14:14 IST 2013
pool-1-thread-2 Start. Time = Tue Oct 29 16:14:15 IST 2013
pool-1-thread-3 Start. Time = Tue Oct 29 16:14:16 IST 2013
pool-1-thread-1 End. Time = Tue Oct 29 16:14:19 IST 2013
pool-1-thread-2 End. Time = Tue Oct 29 16:14:20 IST 2013
pool-1-thread-1 Start. Time = Tue Oct 29 16:14:20 IST 2013
pool-1-thread-3 End. Time = Tue Oct 29 16:14:21 IST 2013
pool-1-thread-4 Start. Time = Tue Oct 29 16:14:21 IST 2013
That’s all for scheduled thread pool executor, you should check other articles about multi-threading atJava Thread Tutorial.