Java Scheduling
-
Schedule a Process Using the
ScheduledExecutorService
Interface Methods in Java -
Schedule a Thread Using the
Timer
Class in Java
Scheduling is the process of executing a task or a function at a fixed interval of time. Scheduling finds its usage in running batch processes, sending event-based triggers like birthday wishes, sending push notifications. These processes must run at a well-defined time based on the conditions and time-interval given.
Schedule a Process Using the ScheduledExecutorService
Interface Methods in Java
package scheduling;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class ScheduleTask {
private static int counter = 0;
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
Runnable executeTask = () -> {
counter++;
System.out.println("Task" + counter);
};
ScheduledFuture<?> scheduleAtFixedRate =
service.scheduleAtFixedRate(executeTask, 5, 1, TimeUnit.SECONDS);
while (true) {
Thread.sleep(1000);
if (counter == 5) {
System.out.println("Stopping the scheduled task!");
scheduleAtFixedRate.cancel(true);
service.shutdown();
break;
}
}
}
}
In the above code, first, a static counter variable is initialized to zero value. The newScheduledThreadPool
is a static method of the Executors
class. The method creates a thread pool that should execute periodically with the parameter given in the argument list. So in our case, a single thread is created for execution as the parameter in the argument list of methods defines the number of thread pools. The method returns an instance of ScheduledExecutorService
that gets stored in the service
reference variable and throws IllegalArgumentException
if the pool size is less than zero.
The Runnable
is an interface that any class can extend and is the functional interface. It has only one static method as the run
method and is intended for the thread to execute. Using the lambda expression expressed as the symbol ()->
parenthesis and an arrow, the structure states that we are not passing any arguments to the run method. We have defined the statements in the definition of the run method. The statement present inside the block will increment the counter variable and print the task in the console output. These all statements are referenced by the variable called the executeTask
variable.
The service
reference variable calls scheduleAtFixedRate
method of ScheduledExecutorService
interface. The method creates and executes the periodic task that should execute after the initial delay and later within the given period. It takes four parameters, a runnable
command that is supposed to execute, and initialDelay
variable is the time to delay first execution, period
denotes the duration between successive executions, and unit
is the unit of time in seconds, minutes, and hours. The thread starts executing as soon as the method gets called.
In the while loop, first, the current running thread is forced to sleep. Thread.sleep()
method temporarily halts the currently executing thread for the defined time. The parameter is the number in milliseconds for which the current working thread should get halt. The method throws IllegalArgumentException
if the value is negative and InterruptedException
if the current thread is interrupted. Later a counter’s value is checked with a defined value. This check is applied to run the while method for a definite number of times. Otherwise, the block will operate for an infinite number that will never terminate. Into the while
block, the scheduleAtFixedRate
variable calls the cancel
method, which cancels the current execution of the thread. The function also takes a Boolean parameter indicating whether the current running thread may interrupt or not.
The method service.shutdown
initiates the shutdown process in which previously submitted tasks are supposed to get executed, and nothing new is accepted.
The output of the above code block is as below.
Task1
Task2
Task3
Task4
Task5
Stopping the scheduled task!
Schedule a Thread Using the Timer
Class in Java
Below is the simple code block that instantiates two user-defined class objects using its constructors. TimerImplementation
is the user-defined class for the same. An instance of Timer
gets created that will create a new thread. The newly created object of a timer will then call the scheduleAtFixedRate
method. This method takes parameters as task
that needs to schedule, delay
delays the task in milliseconds, and period
is the time in milliseconds for successive execution.
package timer;
import java.util.Timer;
public class UsingTimerClass {
public static void main(String[] args) {
TimerImplementation timer1 = new TimerImplementation("Thread1");
TimerImplementation timer2 = new TimerImplementation("Thread2");
Timer t = new Timer();
t.scheduleAtFixedRate(timer1, 0, 2000);
t.scheduleAtFixedRate(timer2, 0, 1000);
}
}
Below is the implementation of the user-defined class. The TimerImplementation
class extends the TimerTask
abstract class that holds a single abstract method named run. We extend the TimerTask
class in a user-defined class then the run
method gets overridden.
The class has one user-defined constructor that sets the user-defined name to the thread object.
We can give actual logic in the thread run
method. It includes a statement as print
which will print the name of the currently executing thread. Thread.currentThread().getName()
returns the name of current executing thread. The sleep method gets called over Thread1
that interrupts the execution for 1000 milliseconds. The sleep
method throws InterruptedException
if any thread interrupts the current thread, and that’s why it gets enclosed in the try-catch
block.
package timer;
import java.util.TimerTask;
public class TimerImplementation extends TimerTask {
private String name;
public TimerImplementation(String n) {
this.name = n;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " " + name);
if ("Thread1".equalsIgnoreCase(name)) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Below is the never-ending output of the above code. Since we have not defined any terminating condition in the run method, the thread will execute endlessly until an external stop is applied to kill the main thread execution.
Timer-0 Thread1
Timer-0 Thread2
Timer-0 Thread2
Timer-0 Thread2
Timer-0 Thread1
Timer-0 Thread2
Timer-0 Thread2
Timer-0 Thread1
Timer-0 Thread2
Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.
LinkedIn