diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml
index c50140237..ed6f8f7f4 100644
--- a/thread-pool/pom.xml
+++ b/thread-pool/pom.xml
@@ -14,5 +14,10 @@
junit
test
+
+ org.mockito
+ mockito-core
+ test
+
diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java b/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java
index f1247101c..3a8464092 100644
--- a/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java
+++ b/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java
@@ -7,7 +7,7 @@ package com.iluwatar.threadpool;
*/
public class CoffeeMakingTask extends Task {
- private static final int TIME_PER_CUP = 300;
+ private static final int TIME_PER_CUP = 100;
public CoffeeMakingTask(int numCups) {
super(numCups * TIME_PER_CUP);
diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java b/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java
index a90bf4bec..2be941406 100644
--- a/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java
+++ b/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java
@@ -7,7 +7,7 @@ package com.iluwatar.threadpool;
*/
public class PotatoPeelingTask extends Task {
- private static final int TIME_PER_POTATO = 500;
+ private static final int TIME_PER_POTATO = 200;
public PotatoPeelingTask(int numPotatoes) {
super(numPotatoes * TIME_PER_POTATO);
diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java b/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java
index 12fecbbd0..2426948b3 100644
--- a/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java
+++ b/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java
@@ -1,19 +1,21 @@
package com.iluwatar.threadpool;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
- *
+ *
* Abstract base class for tasks
*
*/
public abstract class Task {
- private static int nextId = 1;
+ private static final AtomicInteger ID_GENERATOR = new AtomicInteger();
private final int id;
private final int timeMs;
public Task(final int timeMs) {
- this.id = nextId++;
+ this.id = ID_GENERATOR.incrementAndGet();
this.timeMs = timeMs;
}
diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java
new file mode 100644
index 000000000..ab3d47d9a
--- /dev/null
+++ b/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java
@@ -0,0 +1,17 @@
+package com.iluwatar.threadpool;
+
+/**
+ * Date: 12/30/15 - 18:23 PM
+ *
+ * @author Jeroen Meulemeester
+ */
+public class CoffeeMakingTaskTest extends TaskTest {
+
+ /**
+ * Create a new test instance
+ */
+ public CoffeeMakingTaskTest() {
+ super(CoffeeMakingTask::new, 100);
+ }
+
+}
diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java
new file mode 100644
index 000000000..4f9b1496c
--- /dev/null
+++ b/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java
@@ -0,0 +1,17 @@
+package com.iluwatar.threadpool;
+
+/**
+ * Date: 12/30/15 - 18:23 PM
+ *
+ * @author Jeroen Meulemeester
+ */
+public class PotatoPeelingTaskTest extends TaskTest {
+
+ /**
+ * Create a new test instance
+ */
+ public PotatoPeelingTaskTest() {
+ super(PotatoPeelingTask::new, 200);
+ }
+
+}
\ No newline at end of file
diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java
new file mode 100644
index 000000000..f1ef8160f
--- /dev/null
+++ b/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java
@@ -0,0 +1,121 @@
+package com.iluwatar.threadpool;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Date: 12/30/15 - 18:22 PM
+ *
+ * @author Jeroen Meulemeester
+ */
+public abstract class TaskTest {
+
+ /**
+ * The number of tasks used during the concurrency test
+ */
+ private static final int TASK_COUNT = 128 * 1024;
+
+ /**
+ * The number of threads used during the concurrency test
+ */
+ private static final int THREAD_COUNT = 8;
+
+ /**
+ * The task factory, used to create new test items
+ */
+ private final Function factory;
+
+ /**
+ * The expected time needed to run the task 1 single time, in milli seconds
+ */
+ private final int expectedExecutionTime;
+
+ /**
+ * Create a new test instance
+ *
+ * @param factory The task factory, used to create new test items
+ * @param expectedExecutionTime The expected time needed to run the task 1 time, in milli seconds
+ */
+ public TaskTest(final Function factory, final int expectedExecutionTime) {
+ this.factory = factory;
+ this.expectedExecutionTime = expectedExecutionTime;
+ }
+
+ /**
+ * Verify if the generated id is unique for each task, even if the tasks are created in separate
+ * threads
+ */
+ @Test(timeout = 10000)
+ public void testIdGeneration() throws Exception {
+ final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT);
+
+ final List> tasks = new ArrayList<>();
+ for (int i = 0; i < TASK_COUNT; i++) {
+ tasks.add(() -> factory.apply(1).getId());
+ }
+
+ final List ids = service.invokeAll(tasks)
+ .stream()
+ .map(TaskTest::get)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ service.shutdownNow();
+
+ final long uniqueIdCount = ids.stream()
+ .distinct()
+ .count();
+
+ assertEquals(TASK_COUNT, ids.size());
+ assertEquals(TASK_COUNT, uniqueIdCount);
+
+ }
+
+ /**
+ * Verify if the time per execution of a task matches the actual time required to execute the task
+ * a given number of times
+ */
+ @Test
+ public void testTimeMs() {
+ for (int i = 0; i < 10; i++) {
+ assertEquals(this.expectedExecutionTime * i, this.factory.apply(i).getTimeMs());
+ }
+ }
+
+ /**
+ * Verify if the task has some sort of {@link T#toString()}, different from 'null'
+ */
+ @Test
+ public void testToString() {
+ assertNotNull(this.factory.apply(0).toString());
+ }
+
+ /**
+ * Extract the result from a future or returns 'null' when an exception occurred
+ *
+ * @param future The future we want the result from
+ * @param The result type
+ * @return The result or 'null' when a checked exception occurred
+ */
+ private static O get(Future future) {
+ try {
+ return future.get();
+ } catch (InterruptedException | ExecutionException e) {
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java
new file mode 100644
index 000000000..53a1d8694
--- /dev/null
+++ b/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java
@@ -0,0 +1,31 @@
+package com.iluwatar.threadpool;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+/**
+ * Date: 12/30/15 - 18:21 PM
+ *
+ * @author Jeroen Meulemeester
+ */
+public class WorkerTest {
+
+ /**
+ * Verify if a worker does the actual job
+ */
+ @Test
+ public void testRun() {
+ final Task task = mock(Task.class);
+ final Worker worker = new Worker(task);
+ verifyZeroInteractions(task);
+
+ worker.run();
+ verify(task).getTimeMs();
+ verifyNoMoreInteractions(task);
+ }
+
+}
\ No newline at end of file