diff --git a/guest/thread-pools/pom.xml b/guest/thread-pools/pom.xml
new file mode 100644
index 0000000000..72a10213c4
--- /dev/null
+++ b/guest/thread-pools/pom.xml
@@ -0,0 +1,28 @@
+
+ 4.0.0
+ com.stackify
+ thread-pools
+ 0.0.1-SNAPSHOT
+
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.5.1
+
+ 1.8
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/guest/thread-pools/src/main/java/com/stackify/models/Employee.java b/guest/thread-pools/src/main/java/com/stackify/models/Employee.java
new file mode 100644
index 0000000000..65661f38d5
--- /dev/null
+++ b/guest/thread-pools/src/main/java/com/stackify/models/Employee.java
@@ -0,0 +1,28 @@
+package com.stackify.models;
+
+public class Employee {
+ private String name;
+ private double salary;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public double getSalary() {
+ return salary;
+ }
+
+ public void setSalary(double salary) {
+ this.salary = salary;
+ }
+
+ public Employee(String name, double salary) {
+ super();
+ this.name = name;
+ this.salary = salary;
+ }
+}
diff --git a/guest/thread-pools/src/main/java/com/stackify/services/EmployeeService.java b/guest/thread-pools/src/main/java/com/stackify/services/EmployeeService.java
new file mode 100644
index 0000000000..824f87a625
--- /dev/null
+++ b/guest/thread-pools/src/main/java/com/stackify/services/EmployeeService.java
@@ -0,0 +1,9 @@
+package com.stackify.services;
+
+import com.stackify.models.Employee;
+
+public class EmployeeService {
+ public double calculateBonus(Employee employee) {
+ return 0.1 * employee.getSalary();
+ }
+}
diff --git a/guest/thread-pools/src/main/java/com/stackify/threadpools/FactorialTask.java b/guest/thread-pools/src/main/java/com/stackify/threadpools/FactorialTask.java
new file mode 100644
index 0000000000..2dd83d9b20
--- /dev/null
+++ b/guest/thread-pools/src/main/java/com/stackify/threadpools/FactorialTask.java
@@ -0,0 +1,64 @@
+package com.stackify.threadpools;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.RecursiveTask;
+import java.util.stream.IntStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FactorialTask extends RecursiveTask {
+
+ private static final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+
+ private static final long serialVersionUID = 1L;
+
+ private int start = 1;
+ private int n;
+
+ private static final int THRESHOLD = 20;
+
+ public FactorialTask(int n) {
+ this.n = n;
+ }
+
+ public FactorialTask(int start, int n) {
+ logger.info("New FactorialTask Created");
+ this.start = start;
+ this.n = n;
+ }
+
+ @Override
+ protected BigInteger compute() {
+ if ((n - start) >= THRESHOLD) {
+ return ForkJoinTask.invokeAll(createSubtasks())
+ .stream()
+ .map(ForkJoinTask::join)
+ .reduce(BigInteger.ONE, BigInteger::multiply);
+ } else {
+ return calculate(start, n);
+ }
+ }
+
+ private Collection createSubtasks() {
+ List dividedTasks = new ArrayList<>();
+
+ int mid = (start + n) / 2;
+
+ dividedTasks.add(new FactorialTask(start, mid));
+ dividedTasks.add(new FactorialTask(mid + 1, n));
+ return dividedTasks;
+ }
+
+ private BigInteger calculate(int start, int n) {
+ logger.info("Calculate factorial from " + start + " to " + n);
+ return IntStream.rangeClosed(start, n)
+ .mapToObj(BigInteger::valueOf)
+ .reduce(BigInteger.ONE, BigInteger::multiply);
+ }
+
+}
diff --git a/guest/thread-pools/src/main/java/com/stackify/threadpools/ThreadsApplication.java b/guest/thread-pools/src/main/java/com/stackify/threadpools/ThreadsApplication.java
new file mode 100644
index 0000000000..cc9048eee7
--- /dev/null
+++ b/guest/thread-pools/src/main/java/com/stackify/threadpools/ThreadsApplication.java
@@ -0,0 +1,102 @@
+package com.stackify.threadpools;
+
+import java.math.BigInteger;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.stackify.models.Employee;
+import com.stackify.services.EmployeeService;
+
+public class ThreadsApplication {
+
+ private static final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+
+ public static void main(String[] args) {
+ testExecutor();
+ testExecutorService();
+ testScheduledExecutorService();
+ testThreadPoolExecutor();
+ testForkJoinPool();
+ }
+
+ private static EmployeeService employeeService = new EmployeeService();
+
+ public static void testExecutor() {
+ Executor executor = Executors.newSingleThreadExecutor();
+ executor.execute(() -> System.out.println("Single thread pool test"));
+ }
+
+ public static void testExecutorService() {
+
+ Employee employee = new Employee("John", 2000);
+
+ ExecutorService executor = Executors.newFixedThreadPool(10);
+
+ Callable callableTask = () -> {
+ return employeeService.calculateBonus(employee);
+ };
+ Future future = executor.submit(callableTask);
+
+ try {
+ if (future.isDone()) {
+ double result = future.get();
+ System.out.println("Bonus is:" + result);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+
+ executor.shutdown();
+ }
+
+ public static void testScheduledExecutorService() {
+ Employee employee = new Employee("John", 2000);
+
+ ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
+
+ Callable callableTask = () -> {
+ return employeeService.calculateBonus(employee);
+ };
+
+ Future futureScheduled = executor.schedule(callableTask, 2, TimeUnit.MILLISECONDS);
+
+ try {
+ System.out.println("Bonus:" + futureScheduled.get());
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+
+ executor.scheduleAtFixedRate(() -> System.out.println("Fixed Rate Scheduled"), 2, 2000, TimeUnit.MILLISECONDS);
+ executor.scheduleWithFixedDelay(() -> System.out.println("Fixed Delay Scheduled"), 2, 2000, TimeUnit.MILLISECONDS);
+ }
+
+ public static void testThreadPoolExecutor() {
+ ThreadPoolExecutor fixedPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
+ ThreadPoolExecutor cachedPoolExecutor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
+
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 6, 60, TimeUnit.SECONDS, new LinkedBlockingQueue());
+ executor.setMaximumPoolSize(8);
+
+ ScheduledThreadPoolExecutor scheduledExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(5);
+ }
+
+ public static void testForkJoinPool() {
+ ForkJoinPool pool = ForkJoinPool.commonPool();
+ logger.info("Thread Pool Created");
+ BigInteger result = pool.invoke(new FactorialTask(100));
+ System.out.println(result.toString());
+ }
+}