Table of Contents
ToggleScheduledExecutorService in Java with Examples
基於 ExecutorService 的功能實現週期與延遲執行任務,定期排程的工作,交由執行緒池中的執行緒執行,任務在不同週期內執行它的執行緒可能是不同的,由池中空閒的執行緒從任務佇列取出任務執行, Java ScheduledExecutorService Examples 本篇增加了範例,並透過單元測試來驗證產出結果。
檔案目錄
./
+- src
+- test
| +- org
| +- ruoxue
| +- java_147
| +- multithreading
| +- scheduledexecutorservice
| +- ScheduledExecutorServiceWithExamplesTest.java
單元測試
ScheduledExecutorService Java Examples 提供週期與延遲執行任務等, Scheduled Executor Service Java 交由執行緒池中的執行緒執行。
scheduleRunnable
ScheduledExecutorService Java Examples 建立一個執行緒池,固定數量 2 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成,無傳回值, Java ScheduledExecutorService 初始延遲 5 秒後才會開始執行。
@Test
public void scheduleRunnable() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<?>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<?> future = executorService.schedule(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}, 5_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
2023/03/17 10:11:09 T[1] init
2023/03/17 10:11:14 T[12] 5123 task: 1 ready
2023/03/17 10:11:14 T[11] 5122 task: 0 ready
2023/03/17 10:11:15 T[11] 6131 task: 0 finished
2023/03/17 10:11:15 T[12] 6132 task: 1 finished
2023/03/17 10:11:15 T[11] 6133 task: 2 ready
2023/03/17 10:11:16 T[11] 7139 task: 2 finished
scheduleCallable
ScheduledExecutorService Java Examples 建立一個執行緒池,固定數量 2 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成,有傳回值, Java ScheduledExecutorService 初始延遲 5 秒後才會開始執行。
@Test
public void scheduleCallable() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<String>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<String> future = executorService.schedule(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
return e + " OK";
}, 5_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
2023/03/17 10:15:56 T[1] init
2023/03/17 10:16:01 T[11] 5095 task: 0 ready
2023/03/17 10:16:01 T[12] 5094 task: 1 ready
2023/03/17 10:16:02 T[11] 6099 task: 0 finished
2023/03/17 10:16:02 T[12] 6099 task: 1 finished
2023/03/17 10:16:02 T[11] 6100 task: 2 ready
2023/03/17 10:16:03 T[11] 7105 task: 2 finished
scheduleAtFixedRate
ScheduledExecutorService Java Examples 建立一個執行緒池,固定數量 2 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成, Java ScheduledExecutorService 初始延遲 5 秒後才會開始執行,每個週期 1 秒,固定週期執行任務,當任務的執行時間大於週期時,下一個週期任務將在上一個執行完畢後馬上執行,延遲的任務會補上執行。
@Test
public void scheduleAtFixedRate() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<?>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<?> future = executorService.scheduleAtFixedRate(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}, 5_000, 1_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
2023/03/17 11:05:12 T[1] init
2023/03/17 11:05:17 T[11] 5117 task: 0 ready
2023/03/17 11:05:17 T[12] 5118 task: 1 ready
2023/03/17 11:05:18 T[11] 6129 task: 0 finished
2023/03/17 11:05:18 T[12] 6129 task: 1 finished
2023/03/17 11:05:18 T[12] 6132 task: 0 ready
2023/03/17 11:05:18 T[11] 6132 task: 2 ready
2023/03/17 11:05:19 T[12] 7134 task: 0 finished
2023/03/17 11:05:19 T[12] 7136 task: 1 ready
2023/03/17 11:05:19 T[11] 7138 task: 2 finished
2023/03/17 11:05:19 T[11] 7141 task: 2 ready
2023/03/17 11:05:20 T[12] 8140 task: 1 finished
scheduleWithFixedDelay
ScheduledExecutorService Java Examples 建立一個執行緒池,固定數量 2 條執行緒,執行 3 個任務,每個任務耗時 1 秒完成, Java ScheduledExecutorService 初始延遲 5 秒後才會開始執行,固定延遲執行任務,當任務完成時,延遲 3 秒後才會進入下一個週期。
@Test
public void scheduleWithFixedDelay() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<?>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<?> future = executorService.scheduleWithFixedDelay(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}, 5_000, 3_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
2023/03/17 11:06:51 T[1] init
2023/03/17 11:06:56 T[12] 5100 task: 0 ready
2023/03/17 11:06:56 T[11] 5100 task: 1 ready
2023/03/17 11:06:57 T[11] 6108 task: 1 finished
2023/03/17 11:06:57 T[12] 6108 task: 0 finished
2023/03/17 11:06:57 T[12] 6109 task: 2 ready
2023/03/17 11:06:58 T[12] 7112 task: 2 finished
2023/03/17 11:07:00 T[12] 9110 task: 0 ready
2023/03/17 11:07:00 T[11] 9110 task: 1 ready
ScheduledExecutorServiceWithExamplesTest.java
Java ScheduledExecutorService 新增單元測試,驗證 Scheduled Executor Service Java 是否符合預期。
package org.ruoxue.java_147.multithreading.scheduledexecutorservice;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import org.junit.Test;
public class ScheduledExecutorServiceWithExamplesTest {
@Test
public void scheduleRunnable() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<?>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<?> future = executorService.schedule(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}, 5_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
@Test
public void scheduleCallable() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<String>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<String> future = executorService.schedule(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
return e + " OK";
}, 5_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
@Test
public void scheduleAtFixedRate() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<?>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<?> future = executorService.scheduleAtFixedRate(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}, 5_000, 1_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
@Test
public void scheduleWithFixedDelay() {
int poolSize = 2;
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(poolSize);
int taskSize = 3;
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] init", df.format(new Date()), Thread.currentThread().getId()));
long start = System.currentTimeMillis();
List<ScheduledFuture<?>> futures = new ArrayList<>();
IntStream.range(0, taskSize).forEach(e -> {
ScheduledFuture<?> future = executorService.scheduleWithFixedDelay(() -> {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(String.format("%s T[%d] %d task: %d ready", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
TimeUnit.SECONDS.sleep(1);
System.out.println(String.format("%s T[%d] %d task: %d finished", sdf.format(new Date()),
Thread.currentThread().getId(), System.currentTimeMillis() - start, e));
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}, 5_000, 3_000, TimeUnit.MILLISECONDS);
futures.add(future);
});
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
心得分享
Scheduled Executor Service Java 固定週期或固定延遲執行任務,提交到執行緒池中執行,當有空閒的執行緒時,將會從佇列中取出任務執行,然後會傳回 ScheduledFuture 物件,用來判斷任務是否完成、取消任務、取得結果等, Java ScheduledExecutorService 提供了幾種常見方法的操作範例。