ScheduledExecutorService in Java with Examples - Java 147

ScheduledExecutorService in Java with Examples – Java 147

ScheduledExecutorService 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 提供了幾種常見方法的操作範例。

發佈留言