Understanding ScheduledExecutorService and ScheduledThreadPoolExecutor
These examples shows how we can execute one or more tasks periodically by using
ScheduledThreadPoolExecutor.
Creating a Runnable task:
public class MyTask implements Runnable {
private static final long start;
private final String name;
private long repeatCount;
private long taskStart;
static {
start = System.currentTimeMillis();
}
public MyTask (String s) {
this.name = s;
}
@Override
public void run () {
taskStart = System.currentTimeMillis();
try {
Thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
repeatCount++;
printTaskInfo();
}
private void printTaskInfo () {
StringBuilder builder = new StringBuilder(" ")
.append(name)
.append(" - Repeat count: ")
.append(repeatCount)
.append(" - Exec At: ")
.append(taskStart - start)
.append(" - Task duration: " + (System.currentTimeMillis()
- taskStart));
System.out.println(builder);
}
public String getName () {
return name;
}
}
A util class to print executor and submitted task details
public class PoolUtil {
public static void showPoolDetails (ThreadPoolExecutor executor, String tasksDetails) {
StringBuilder builder = new StringBuilder();
builder.append("Executor: ")
.append(executor.getClass())
.append("\ncore pool size: ")
.append(executor.getCorePoolSize())
.append("\nTask submitted: ")
.append(executor.getTaskCount())
.append("\nQueue: ")
.append(executor.getQueue()
.getClass())
.append("\nTasks details: ")
.append(tasksDetails)
.append("\n");
System.out.println(builder);
}
}
Creating ScheduledThreadPoolExecutor instance of pool size 1 and executing 2 fixed-delayed tasks :
It will act like a Timer because of pool size 1. It will run multiple tasks sequentially rather than in parallel.
public class ScheduledMultipleFixedDelayTasks {
public static void main (String[] args) throws InterruptedException {
// equivalent to Executors.newSingleThreadScheduledExecutor();
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
service.scheduleWithFixedDelay(new MyTask("Task 1"), 500,
1000, TimeUnit.MILLISECONDS);
service.scheduleWithFixedDelay(new MyTask("Task 2"), 500,
1000, TimeUnit.MILLISECONDS);
PoolUtil.showPoolDetails((ThreadPoolExecutor) service, "For each task" +
" initial delay: 500 ms," +
" delay period: 1000 ms," +
" repeat policy: fixed-delay");
TimeUnit.SECONDS.sleep(10);
service.shutdown();
}
}
Note that we are shutting down the pool after 10 secs (same with all following examples), otherwise there will be infinite output. In real project scenarios, you might not want to do that.
Output
Executor: class java.util.concurrent.ScheduledThreadPoolExecutor
core pool size: 1
Task submitted: 2
Queue: class java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
Tasks details: For each task initial delay: 500 ms, delay period: 1000 ms, repeat policy: fixed-delay
Task 1 - Repeat count: 1 - Exec At: 502 - Task duration: 251
Task 2 - Repeat count: 1 - Exec At: 753 - Task duration: 250
Task 1 - Repeat count: 2 - Exec At: 1753 - Task duration: 250
Task 2 - Repeat count: 2 - Exec At: 2003 - Task duration: 250
Task 1 - Repeat count: 3 - Exec At: 3015 - Task duration: 250
Task 2 - Repeat count: 3 - Exec At: 3265 - Task duration: 250
Task 1 - Repeat count: 4 - Exec At: 4265 - Task duration: 265
Task 2 - Repeat count: 4 - Exec At: 4530 - Task duration: 264
Task 1 - Repeat count: 5 - Exec At: 5534 - Task duration: 255
Task 2 - Repeat count: 5 - Exec At: 5805 - Task duration: 254
Task 1 - Repeat count: 6 - Exec At: 6790 - Task duration: 251
Task 2 - Repeat count: 6 - Exec At: 7059 - Task duration: 264
Task 1 - Repeat count: 7 - Exec At: 8041 - Task duration: 251
Task 2 - Repeat count: 7 - Exec At: 8324 - Task duration: 251
Task 1 - Repeat count: 8 - Exec At: 9293 - Task duration: 251
Task 2 - Repeat count: 8 - Exec At: 9575 - Task duration: 250
Creating pool size 2, executing 2 fixed-delayed tasks:
You will notice how two tasks run in parallel as opposed to two tasks run in sequence submitted to Timer or our last example with core pool size of 1.
public class ScheduledMultipleFixedDelayTasks2 {
public static void main (String[] args) throws InterruptedException {
// equivalent to Executors.newScheduledThreadPool(2)
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2);
service.scheduleWithFixedDelay(new MyTask("Task 1"), 500, 1000, TimeUnit.MILLISECONDS);
service.scheduleWithFixedDelay(new MyTask("Task 2"), 500, 1000, TimeUnit.MILLISECONDS);
PoolUtil.showPoolDetails((ThreadPoolExecutor) service, "For each task" +
" initial delay: 500 ms," +
" delay period: 1000 ms," +
" repeat policy: fixed-delay");
TimeUnit.SECONDS.sleep(10);
service.shutdown();
}
}
Output
Executor: class java.util.concurrent.ScheduledThreadPoolExecutor
core pool size: 2
Task submitted: 2
Queue: class java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
Tasks details: For each task initial delay: 500 ms, delay period: 1000 ms, repeat policy: fixed-delay
Task 2 - Repeat count: 1 - Exec At: 501 - Task duration: 250
Task 1 - Repeat count: 1 - Exec At: 501 - Task duration: 250
Task 1 - Repeat count: 2 - Exec At: 1752 - Task duration: 250
Task 2 - Repeat count: 2 - Exec At: 1752 - Task duration: 250
Task 1 - Repeat count: 3 - Exec At: 3003 - Task duration: 250
Task 2 - Repeat count: 3 - Exec At: 3003 - Task duration: 250
Task 1 - Repeat count: 4 - Exec At: 4253 - Task duration: 251
Task 2 - Repeat count: 4 - Exec At: 4253 - Task duration: 251
Task 1 - Repeat count: 5 - Exec At: 5504 - Task duration: 250
Task 2 - Repeat count: 5 - Exec At: 5504 - Task duration: 250
Task 2 - Repeat count: 6 - Exec At: 6767 - Task duration: 255
Task 1 - Repeat count: 6 - Exec At: 6767 - Task duration: 255
Task 1 - Repeat count: 7 - Exec At: 8028 - Task duration: 256
Task 2 - Repeat count: 7 - Exec At: 8028 - Task duration: 256
Task 2 - Repeat count: 8 - Exec At: 9295 - Task duration: 256
Task 1 - Repeat count: 8 - Exec At: 9295 - Task duration: 256
Creating pool size 1, executing 2 fixed-rate tasks:
public class ScheduledMultipleFixedRateTasks {
public static void main (String[] args) throws InterruptedException {
// equivalent to Executor.newSingleThreadScheduledExecutor()
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
service.scheduleAtFixedRate(new MyTask("Task 1"), 500, 1000, TimeUnit.MILLISECONDS);
service.scheduleAtFixedRate(new MyTask("Task 2"), 500, 1000, TimeUnit.MILLISECONDS);
PoolUtil.showPoolDetails((ThreadPoolExecutor) service, "For each task" +
" initial delay: 500 ms," +
" delay period: 1000 ms," +
" repeat policy: fixed-rate");
TimeUnit.SECONDS.sleep(10);
service.shutdown();
}
}
Output
Executor: class java.util.concurrent.ScheduledThreadPoolExecutor
core pool size: 1
Task submitted: 2
Queue: class java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
Tasks details: For each task initial delay: 500 ms, delay period: 1000 ms, repeat policy: fixed-rate
Task 1 - Repeat count: 1 - Exec At: 515 - Task duration: 250
Task 2 - Repeat count: 1 - Exec At: 765 - Task duration: 250
Task 1 - Repeat count: 2 - Exec At: 1502 - Task duration: 251
Task 2 - Repeat count: 2 - Exec At: 1753 - Task duration: 251
Task 1 - Repeat count: 3 - Exec At: 2501 - Task duration: 250
Task 2 - Repeat count: 3 - Exec At: 2751 - Task duration: 250
Task 1 - Repeat count: 4 - Exec At: 3509 - Task duration: 263
Task 2 - Repeat count: 4 - Exec At: 3772 - Task duration: 250
Task 1 - Repeat count: 5 - Exec At: 4515 - Task duration: 256
Task 2 - Repeat count: 5 - Exec At: 4771 - Task duration: 255
Task 1 - Repeat count: 6 - Exec At: 5507 - Task duration: 255
Task 2 - Repeat count: 6 - Exec At: 5762 - Task duration: 265
Task 1 - Repeat count: 7 - Exec At: 6516 - Task duration: 250
Task 2 - Repeat count: 7 - Exec At: 6766 - Task duration: 255
Task 1 - Repeat count: 8 - Exec At: 7501 - Task duration: 255
Task 2 - Repeat count: 8 - Exec At: 7756 - Task duration: 256
Task 1 - Repeat count: 9 - Exec At: 8515 - Task duration: 255
Task 2 - Repeat count: 9 - Exec At: 8770 - Task duration: 256
Task 1 - Repeat count: 10 - Exec At: 9506 - Task duration: 256
Task 2 - Repeat count: 10 - Exec At: 9762 - Task duration: 265
Creating pool size 2, executing 2 fixed-rate tasks:
public class ScheduledMultipleFixedRateTasks2 {
public static void main (String[] args) throws InterruptedException {
// equivalent to Executors.newScheduledThreadPool(2)
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2);
service.scheduleAtFixedRate(new MyTask("Task 1"), 500, 1000, TimeUnit.MILLISECONDS);
service.scheduleAtFixedRate(new MyTask("Task 2"), 500, 1000, TimeUnit.MILLISECONDS);
PoolUtil.showPoolDetails((ThreadPoolExecutor) service, "For each task" +
" initial delay: 500 ms," +
" delay period: 1000 ms," +
" repeat policy: fixed-rate");
TimeUnit.SECONDS.sleep(10);
service.shutdown();
}
}
Output
Executor: class java.util.concurrent.ScheduledThreadPoolExecutor
core pool size: 2
Task submitted: 2
Queue: class java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
Tasks details: For each task initial delay: 500 ms, delay period: 1000 ms, repeat policy: fixed-rate
Task 2 - Repeat count: 1 - Exec At: 509 - Task duration: 256
Task 1 - Repeat count: 1 - Exec At: 509 - Task duration: 256
Task 2 - Repeat count: 2 - Exec At: 1501 - Task duration: 256
Task 1 - Repeat count: 2 - Exec At: 1501 - Task duration: 256
Task 1 - Repeat count: 3 - Exec At: 2501 - Task duration: 264
Task 2 - Repeat count: 3 - Exec At: 2501 - Task duration: 264
Task 1 - Repeat count: 4 - Exec At: 3502 - Task duration: 251
Task 2 - Repeat count: 4 - Exec At: 3502 - Task duration: 251
Task 1 - Repeat count: 5 - Exec At: 4513 - Task duration: 255
Task 2 - Repeat count: 5 - Exec At: 4513 - Task duration: 255
Task 2 - Repeat count: 6 - Exec At: 5502 - Task duration: 250
Task 1 - Repeat count: 6 - Exec At: 5502 - Task duration: 250
Task 2 - Repeat count: 7 - Exec At: 6501 - Task duration: 251
Task 1 - Repeat count: 7 - Exec At: 6501 - Task duration: 251
Task 2 - Repeat count: 8 - Exec At: 7501 - Task duration: 250
Task 1 - Repeat count: 8 - Exec At: 7501 - Task duration: 250
Task 1 - Repeat count: 9 - Exec At: 8502 - Task duration: 250
Task 2 - Repeat count: 9 - Exec At: 8502 - Task duration: 250
Task 2 - Repeat count: 10 - Exec At: 9502 - Task duration: 255
Task 1 - Repeat count: 10 - Exec At: 9502 - Task duration: 255
Creating pool size 1, executing 1 fixed-delayed task:
public class ScheduledSingleFixedDelayTask {
public static void main (String[] args) throws InterruptedException {
// equivalent to Executors.newSingleThreadScheduledExecutor()
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
service.scheduleWithFixedDelay(new MyTask("Task 1"), 500, 1000, TimeUnit.MILLISECONDS);
PoolUtil.showPoolDetails((ThreadPoolExecutor) service, "For each task" +
" initial delay: 500 ms," +
" delay period: 1000 ms," +
" repeat policy: fixed-delay");
TimeUnit.SECONDS.sleep(10);
service.shutdown();
}
}
Output
Executor: class java.util.concurrent.ScheduledThreadPoolExecutor
core pool size: 1
Task submitted: 1
Queue: class java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
Tasks details: For each task initial delay: 500 ms, delay period: 1000 ms, repeat policy: fixed-delay
Task 1 - Repeat count: 1 - Exec At: 503 - Task duration: 256
Task 1 - Repeat count: 2 - Exec At: 1764 - Task duration: 256
Task 1 - Repeat count: 3 - Exec At: 3032 - Task duration: 251
Task 1 - Repeat count: 4 - Exec At: 4292 - Task duration: 262
Task 1 - Repeat count: 5 - Exec At: 5554 - Task duration: 250
Task 1 - Repeat count: 6 - Exec At: 6805 - Task duration: 255
Task 1 - Repeat count: 7 - Exec At: 8074 - Task duration: 262
Task 1 - Repeat count: 8 - Exec At: 9341 - Task duration: 263
Creating pool size 1, executing 1 fixed-rate task:
public class ScheduledSingleFixedRateTask {
public static void main (String[] args) throws InterruptedException {
System.out.println("Thread pool size: 1.\nTask submitted: 1" +
"\n\nEach tasks have:" +
"\nSchedule policy: fixed-rate" +
"\nInitial delay: 500\ndelay period: 1000:\n");
// equivalent to Executors.newSingleThreadScheduledExecutor()
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1);
service.scheduleAtFixedRate(new MyTask("Task 1"), 500, 1000, TimeUnit.MILLISECONDS);
PoolUtil.showPoolDetails((ThreadPoolExecutor) service, "For each task" +
" initial delay: 500 ms," +
" delay period: 1000 ms," +
" repeat policy: fixed-rate");
TimeUnit.SECONDS.sleep(10);
service.shutdown();
}
}
Output
Thread pool size: 1.
Task submitted: 1
Each tasks have:
Schedule policy: fixed-rate
Initial delay: 500
delay period: 1000:
Executor: class java.util.concurrent.ScheduledThreadPoolExecutor
core pool size: 1
Task submitted: 1
Queue: class java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue
Tasks details: For each task initial delay: 500 ms, delay period: 1000 ms, repeat policy: fixed-rate
Task 1 - Repeat count: 1 - Exec At: 506 - Task duration: 250
Task 1 - Repeat count: 2 - Exec At: 1505 - Task duration: 259
Task 1 - Repeat count: 3 - Exec At: 2502 - Task duration: 255
Task 1 - Repeat count: 4 - Exec At: 3510 - Task duration: 262
Task 1 - Repeat count: 5 - Exec At: 4501 - Task duration: 260
Task 1 - Repeat count: 6 - Exec At: 5502 - Task duration: 256
Task 1 - Repeat count: 7 - Exec At: 6511 - Task duration: 257
Task 1 - Repeat count: 8 - Exec At: 7506 - Task duration: 256
Task 1 - Repeat count: 9 - Exec At: 8513 - Task duration: 256
Task 1 - Repeat count: 10 - Exec At: 9509 - Task duration: 250
Original Post