From f36d7f1ac2bc94d20e6f9fe46ac1951d5d643486 Mon Sep 17 00:00:00 2001 From: Felipe Reis Date: Wed, 25 Jan 2017 21:57:36 -0200 Subject: [PATCH] BAEL-612: Single and multi threaded Future usage. --- .../concurrent/future/SquareCalculator.java | 24 +++++ .../future/SquareCalculatorUnitTest.java | 94 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java create mode 100644 core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java diff --git a/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java b/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java new file mode 100644 index 0000000000..2cb27025ee --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/future/SquareCalculator.java @@ -0,0 +1,24 @@ +package com.baeldung.concurrent.future; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +public class SquareCalculator { + + private final ExecutorService executor; + + public SquareCalculator(ExecutorService executor) { + this.executor = executor; + } + + public Future calculate(Integer input) { + return executor.submit(new Callable() { + @Override + public Integer call() throws Exception { + Thread.sleep(1000); + return input * input; + } + }); + } +} diff --git a/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java b/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java new file mode 100644 index 0000000000..69c802feb8 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/future/SquareCalculatorUnitTest.java @@ -0,0 +1,94 @@ +package com.baeldung.concurrent.future; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; + +public class SquareCalculatorUnitTest { + + @Rule + public TestName name = new TestName(); + + private long start; + + private SquareCalculator squareCalculator; + + @Test + public void givenExecutorIsSingleThreaded_whenTwoExecutionsAreTriggered_thenRunInSequence() throws InterruptedException, ExecutionException { + squareCalculator = new SquareCalculator(Executors.newSingleThreadExecutor()); + + Future result1 = squareCalculator.calculate(4); + Future result2 = squareCalculator.calculate(1000); + + while (!result1.isDone() || !result2.isDone()) { + System.out.println(String.format("Task 1 is %s and Task 2 is %s.", result1.isDone() ? "done" : "not done", result2.isDone() ? "done" : "not done")); + + Thread.sleep(300); + } + + assertEquals(16, result1.get().intValue()); + assertEquals(1000000, result2.get().intValue()); + } + + @Test(expected = TimeoutException.class) + public void whenGetWithTimeoutLowerThanExecutionTime_thenThrowException() throws InterruptedException, ExecutionException, TimeoutException { + squareCalculator = new SquareCalculator(Executors.newSingleThreadExecutor()); + + Future result = squareCalculator.calculate(4); + + result.get(500, TimeUnit.MILLISECONDS); + } + + @Test + public void givenExecutorIsMultiThreaded_whenTwoExecutionsAreTriggered_thenRunInParallel() throws InterruptedException, ExecutionException { + squareCalculator = new SquareCalculator(Executors.newFixedThreadPool(2)); + + Future result1 = squareCalculator.calculate(4); + Future result2 = squareCalculator.calculate(1000); + + while (!result1.isDone() || !result2.isDone()) { + System.out.println(String.format("Task 1 is %s and Task 2 is %s.", result1.isDone() ? "done" : "not done", result2.isDone() ? "done" : "not done")); + + Thread.sleep(300); + } + + assertEquals(16, result1.get().intValue()); + assertEquals(1000000, result2.get().intValue()); + } + + @Test(expected = CancellationException.class) + public void whenCancelFutureAndCallGet_thenThrowException() throws InterruptedException, ExecutionException, TimeoutException { + squareCalculator = new SquareCalculator(Executors.newSingleThreadExecutor()); + + Future result = squareCalculator.calculate(4); + + boolean canceled = result.cancel(true); + + assertTrue("Future was canceled", canceled); + assertTrue("Future was canceled", result.isCancelled()); + + result.get(); + } + + @Before + public void start() { + start = System.currentTimeMillis(); + } + + @After + public void end() { + System.out.println(String.format("Test %s took %s ms \n", name.getMethodName(), System.currentTimeMillis() - start)); + } +}