From f7697918f2cb715b5e314729cf6aedaaaf5afe86 Mon Sep 17 00:00:00 2001 From: mthomas Date: Sat, 8 Feb 2020 04:51:16 -0600 Subject: [PATCH 1/8] BAEL-3817 - Add unit tests showing the difference between the Spring ThreadPoolTaskExecutor's corePoolSize and maxPoolSize properties --- spring-threads/.gitignore | 12 ++ spring-threads/README.md | 10 ++ spring-threads/pom.xml | 29 ++++ .../ThreadPoolTaskExecutorUnitTest.java | 130 ++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 spring-threads/.gitignore create mode 100644 spring-threads/README.md create mode 100644 spring-threads/pom.xml create mode 100644 spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java diff --git a/spring-threads/.gitignore b/spring-threads/.gitignore new file mode 100644 index 0000000000..08259abdaf --- /dev/null +++ b/spring-threads/.gitignore @@ -0,0 +1,12 @@ +RemoteSystemsTempFiles/ +.classpath +.project +.settings/ +bin/ +.metadata/ +docs/*.autosave +.recommenders/ +build/ +.gradle/ +.DS_Store +.idea/ \ No newline at end of file diff --git a/spring-threads/README.md b/spring-threads/README.md new file mode 100644 index 0000000000..7f4ee1d6a1 --- /dev/null +++ b/spring-threads/README.md @@ -0,0 +1,10 @@ +## Spring Threads + +This module contains articles about threading using threads, specifically Spring's ThreadPoolTaskExecutor + +### Relevant Articles: +- [Introduction to Thread Pools in Java](https://www.baeldung.com/thread-pool-java-and-guava) +- [How To Do @Async in Spring](https://www.baeldung.com/spring-async) +- [A Guide to the Spring Task Scheduler](https://www.baeldung.com/spring-task-scheduler) +- [A Guide to the Java ExecutorService](https://www.baeldung.com/java-executor-service-tutorial) + diff --git a/spring-threads/pom.xml b/spring-threads/pom.xml new file mode 100644 index 0000000000..bf3d460ac0 --- /dev/null +++ b/spring-threads/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + spring-threads + 0.0.1-SNAPSHOT + spring-threads + jar + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../parent-spring-5 + + + + + org.springframework + spring-context + ${spring.version} + + + + + 3.12.2 + + + diff --git a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java new file mode 100644 index 0000000000..196f67a08f --- /dev/null +++ b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java @@ -0,0 +1,130 @@ +package com.baeldung.threading; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +public class ThreadPoolTaskExecutorUnitTest { + + @Test + public void whenUsingDefaults_thenSingleThread() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + taskExecutor.execute(() -> { + try { + Thread.sleep(10L * ThreadLocalRandom.current().nextLong(1, 10)); + countDownLatch.countDown(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(1, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFive_thenFiveThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + taskExecutor.execute(() -> { + try { + Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); + countDownLatch.countDown(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(5, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFive_andMaxPoolSizeTen_thenFiveThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + taskExecutor.execute(() -> { + try { + Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); + countDownLatch.countDown(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(5, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFive_andMaxPoolSizeTen_andQueueCapacityZero_thenTenThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.setQueueCapacity(0); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 10; i++) { + taskExecutor.execute(() -> { + try { + Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); + countDownLatch.countDown(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(10, taskExecutor.getPoolSize()); + } + } + + @Test + public void whenCorePoolSizeFive_andMaxPoolSizeTen_andQueueCapacityTen_thenTenThreads() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.setCorePoolSize(5); + taskExecutor.setMaxPoolSize(10); + taskExecutor.setQueueCapacity(10); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + for (int i = 0; i < 20; i++) { + taskExecutor.execute(() -> { + try { + Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); + countDownLatch.countDown(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + } + + while (countDownLatch.getCount() > 0) { + Assert.assertEquals(10, taskExecutor.getPoolSize()); + } + } +} From 4ab52b0e37b242b9a2e2efc2f162ffdf5dbe3e1c Mon Sep 17 00:00:00 2001 From: mthomas Date: Sat, 8 Feb 2020 04:54:27 -0600 Subject: [PATCH 2/8] Fix unit test names --- .../baeldung/threading/ThreadPoolTaskExecutorUnitTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java index 196f67a08f..9a370b7263 100644 --- a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java +++ b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java @@ -55,7 +55,7 @@ public class ThreadPoolTaskExecutorUnitTest { } @Test - public void whenCorePoolSizeFive_andMaxPoolSizeTen_thenFiveThreads() { + public void whenCorePoolSizeFiveAndMaxPoolSizeTen_thenFiveThreads() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); @@ -79,7 +79,7 @@ public class ThreadPoolTaskExecutorUnitTest { } @Test - public void whenCorePoolSizeFive_andMaxPoolSizeTen_andQueueCapacityZero_thenTenThreads() { + public void whenCorePoolSizeFiveAndMaxPoolSizeTenAndQueueCapacityZero_thenTenThreads() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); @@ -104,7 +104,7 @@ public class ThreadPoolTaskExecutorUnitTest { } @Test - public void whenCorePoolSizeFive_andMaxPoolSizeTen_andQueueCapacityTen_thenTenThreads() { + public void whenCorePoolSizeFiveAndMaxPoolSizeTenAndQueueCapacityTen_thenTenThreads() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); From 79af99356eec3617c9128ea4f622afbc7a05fd0d Mon Sep 17 00:00:00 2001 From: mthomas Date: Sat, 8 Feb 2020 04:59:31 -0600 Subject: [PATCH 3/8] Remove unused property --- spring-threads/pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spring-threads/pom.xml b/spring-threads/pom.xml index bf3d460ac0..4513c627b9 100644 --- a/spring-threads/pom.xml +++ b/spring-threads/pom.xml @@ -22,8 +22,4 @@ - - 3.12.2 - - From 9d9ad1663668e5162a1f7879b8f5f499fa4cf344 Mon Sep 17 00:00:00 2001 From: mthomas Date: Fri, 14 Feb 2020 08:33:28 -0600 Subject: [PATCH 4/8] Extract out common code for starting threads into startThreads method --- .../ThreadPoolTaskExecutorUnitTest.java | 66 +++++-------------- 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java index 9a370b7263..aa823b7dcd 100644 --- a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java +++ b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java @@ -9,22 +9,26 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class ThreadPoolTaskExecutorUnitTest { - @Test - public void whenUsingDefaults_thenSingleThread() { - ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); - taskExecutor.afterPropertiesSet(); - - CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { + private void startThreads(ThreadPoolTaskExecutor taskExecutor, CountDownLatch countDownLatch, int numThreads) { + for (int i = 0; i < numThreads; i++) { taskExecutor.execute(() -> { try { - Thread.sleep(10L * ThreadLocalRandom.current().nextLong(1, 10)); + Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); countDownLatch.countDown(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } + } + + @Test + public void whenUsingDefaults_thenSingleThread() { + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.afterPropertiesSet(); + + CountDownLatch countDownLatch = new CountDownLatch(10); + this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(1, taskExecutor.getPoolSize()); @@ -38,16 +42,7 @@ public class ThreadPoolTaskExecutorUnitTest { taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - taskExecutor.execute(() -> { - try { - Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); - countDownLatch.countDown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - } + this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(5, taskExecutor.getPoolSize()); @@ -62,16 +57,7 @@ public class ThreadPoolTaskExecutorUnitTest { taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - taskExecutor.execute(() -> { - try { - Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); - countDownLatch.countDown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - } + this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(5, taskExecutor.getPoolSize()); @@ -87,16 +73,7 @@ public class ThreadPoolTaskExecutorUnitTest { taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - taskExecutor.execute(() -> { - try { - Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); - countDownLatch.countDown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - } + this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(10, taskExecutor.getPoolSize()); @@ -111,17 +88,8 @@ public class ThreadPoolTaskExecutorUnitTest { taskExecutor.setQueueCapacity(10); taskExecutor.afterPropertiesSet(); - CountDownLatch countDownLatch = new CountDownLatch(10); - for (int i = 0; i < 20; i++) { - taskExecutor.execute(() -> { - try { - Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); - countDownLatch.countDown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - }); - } + CountDownLatch countDownLatch = new CountDownLatch(20); + this.startThreads(taskExecutor, countDownLatch, 20); while (countDownLatch.getCount() > 0) { Assert.assertEquals(10, taskExecutor.getPoolSize()); From a0bd20a937b9ada3c509d3959a2f51949036ce0f Mon Sep 17 00:00:00 2001 From: mthomas Date: Fri, 14 Feb 2020 08:36:20 -0600 Subject: [PATCH 5/8] Make method package private --- .../com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java index aa823b7dcd..0d927ebe69 100644 --- a/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java +++ b/spring-threads/src/test/java/com/baeldung/threading/ThreadPoolTaskExecutorUnitTest.java @@ -9,7 +9,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; public class ThreadPoolTaskExecutorUnitTest { - private void startThreads(ThreadPoolTaskExecutor taskExecutor, CountDownLatch countDownLatch, int numThreads) { + void startThreads(ThreadPoolTaskExecutor taskExecutor, CountDownLatch countDownLatch, int numThreads) { for (int i = 0; i < numThreads; i++) { taskExecutor.execute(() -> { try { From 88519178e0fee4dbeb9d7179e72579dd3234477d Mon Sep 17 00:00:00 2001 From: mthomas Date: Fri, 14 Feb 2020 09:59:20 -0600 Subject: [PATCH 6/8] Fix README.md links to articles on thread pools and Spring --- spring-threads/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spring-threads/README.md b/spring-threads/README.md index 7f4ee1d6a1..72543ae4ff 100644 --- a/spring-threads/README.md +++ b/spring-threads/README.md @@ -1,10 +1,7 @@ ## Spring Threads -This module contains articles about threading using threads, specifically Spring's ThreadPoolTaskExecutor +This module contains articles about threading using thread pools, specifically Spring's ThreadPoolTaskExecutor ### Relevant Articles: -- [Introduction to Thread Pools in Java](https://www.baeldung.com/thread-pool-java-and-guava) -- [How To Do @Async in Spring](https://www.baeldung.com/spring-async) -- [A Guide to the Spring Task Scheduler](https://www.baeldung.com/spring-task-scheduler) -- [A Guide to the Java ExecutorService](https://www.baeldung.com/java-executor-service-tutorial) +- [ThreadPoolTaskExecutor corePoolSize vs. maxPoolSize – What’s the Difference?](https://baeldung.com/threadpool-task-executor-corepoolsize-maxpoolsize) From ab2ef656983c85a0f3c8996c880d4d187c498c41 Mon Sep 17 00:00:00 2001 From: mthomas Date: Fri, 14 Feb 2020 10:10:53 -0600 Subject: [PATCH 7/8] Change title of article in README to reflect new article title --- spring-threads/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-threads/README.md b/spring-threads/README.md index 72543ae4ff..8c496f17be 100644 --- a/spring-threads/README.md +++ b/spring-threads/README.md @@ -3,5 +3,5 @@ This module contains articles about threading using thread pools, specifically Spring's ThreadPoolTaskExecutor ### Relevant Articles: -- [ThreadPoolTaskExecutor corePoolSize vs. maxPoolSize – What’s the Difference?](https://baeldung.com/threadpool-task-executor-corepoolsize-maxpoolsize) +- [ThreadPoolTaskExecutor corePoolSize vs. maxPoolSize](https://baeldung.com/threadpool-task-executor-corepoolsize-maxpoolsize) From 70e90bf9bd6514185c1984acde76fbb1ee3c9532 Mon Sep 17 00:00:00 2001 From: mthomas Date: Wed, 19 Feb 2020 01:40:34 -0600 Subject: [PATCH 8/8] - Remove the README.md file - Remove .gitignore - Aggregate this module in the root pom.xml so that it is integrated into the automated builds. --- pom.xml | 3 ++- spring-threads/.gitignore | 12 ------------ spring-threads/README.md | 7 ------- 3 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 spring-threads/.gitignore delete mode 100644 spring-threads/README.md diff --git a/pom.xml b/pom.xml index 6e6316edd6..15b695b9ad 100644 --- a/pom.xml +++ b/pom.xml @@ -641,7 +641,7 @@ spring-boot-parent spring-boot-rest spring-boot-security - + spring-caching spring-cloud @@ -728,6 +728,7 @@ spring-static-resources spring-swagger-codegen + spring-threads spring-thymeleaf spring-thymeleaf-2 diff --git a/spring-threads/.gitignore b/spring-threads/.gitignore deleted file mode 100644 index 08259abdaf..0000000000 --- a/spring-threads/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -RemoteSystemsTempFiles/ -.classpath -.project -.settings/ -bin/ -.metadata/ -docs/*.autosave -.recommenders/ -build/ -.gradle/ -.DS_Store -.idea/ \ No newline at end of file diff --git a/spring-threads/README.md b/spring-threads/README.md deleted file mode 100644 index 8c496f17be..0000000000 --- a/spring-threads/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Spring Threads - -This module contains articles about threading using thread pools, specifically Spring's ThreadPoolTaskExecutor - -### Relevant Articles: -- [ThreadPoolTaskExecutor corePoolSize vs. maxPoolSize](https://baeldung.com/threadpool-task-executor-corepoolsize-maxpoolsize) -