[BAEL-6486] - Returning a Value After Finishing Thread's Job in Java (#14101)
* feat: threads with return value * pmd violation
This commit is contained in:
parent
9ff3b1dd9b
commit
f265b51841
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.task;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class FactorialCalculator {
|
||||
|
||||
public static BigInteger factorial(BigInteger end) {
|
||||
BigInteger start = BigInteger.ONE;
|
||||
BigInteger res = BigInteger.ONE;
|
||||
|
||||
for (int i = start.add(BigInteger.ONE)
|
||||
.intValue(); i <= end.intValue(); i++) {
|
||||
res = res.multiply(BigInteger.valueOf(i));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static BigInteger factorial(BigInteger start, BigInteger end) {
|
||||
BigInteger res = start;
|
||||
|
||||
for (int i = start.add(BigInteger.ONE)
|
||||
.intValue(); i <= end.intValue(); i++) {
|
||||
res = res.multiply(BigInteger.valueOf(i));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.task.callable;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class CallableExecutor {
|
||||
|
||||
public BigInteger execute(List<CallableFactorialTask> tasks) {
|
||||
|
||||
BigInteger result = BigInteger.ZERO;
|
||||
|
||||
ExecutorService cachedPool = Executors.newCachedThreadPool();
|
||||
|
||||
List<Future<BigInteger>> futures;
|
||||
|
||||
try {
|
||||
futures = cachedPool.invokeAll(tasks);
|
||||
} catch (InterruptedException e) {
|
||||
// exception handling example
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
for (Future<BigInteger> future : futures) {
|
||||
try {
|
||||
result = result.add(future.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
// exception handling example
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.task.callable;
|
||||
|
||||
import static com.baeldung.concurrent.threadreturnvalue.task.FactorialCalculator.factorial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public class CallableFactorialTask implements Callable<BigInteger> {
|
||||
|
||||
private final Integer value;
|
||||
|
||||
public CallableFactorialTask(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger call() {
|
||||
return factorial(BigInteger.valueOf(value));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.task.fork;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class ForkExecutor {
|
||||
|
||||
private final ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
|
||||
|
||||
public BigInteger execute(ForkFactorialTask forkFactorial) {
|
||||
return forkJoinPool.invoke(forkFactorial);
|
||||
}
|
||||
|
||||
public BigInteger execute(List<Callable<BigInteger>> forkFactorials) {
|
||||
List<Future<BigInteger>> futures = forkJoinPool.invokeAll(forkFactorials);
|
||||
|
||||
BigInteger result = BigInteger.ZERO;
|
||||
|
||||
for (Future<BigInteger> future : futures) {
|
||||
try {
|
||||
result = result.add(future.get());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
// exception handling example
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.task.fork;
|
||||
|
||||
import static com.baeldung.concurrent.threadreturnvalue.task.FactorialCalculator.factorial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
|
||||
public class ForkFactorialTask extends RecursiveTask<BigInteger> {
|
||||
|
||||
private final int start;
|
||||
private final int end;
|
||||
private final int threshold;
|
||||
|
||||
public ForkFactorialTask(int end, int threshold) {
|
||||
this.start = 1;
|
||||
this.end = end;
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
public ForkFactorialTask(int start, int end, int threshold) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.threshold = threshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BigInteger compute() {
|
||||
|
||||
BigInteger sum = BigInteger.ONE;
|
||||
|
||||
if (end - start > threshold) {
|
||||
|
||||
int middle = (end + start) / 2;
|
||||
|
||||
return sum.multiply(new ForkFactorialTask(start, middle, threshold).fork()
|
||||
.join()
|
||||
.multiply(new ForkFactorialTask(middle + 1, end, threshold).fork()
|
||||
.join()));
|
||||
}
|
||||
|
||||
return sum.multiply(factorial(BigInteger.valueOf(start), BigInteger.valueOf(end)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.callable;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.concurrent.threadreturnvalue.task.callable.CallableExecutor;
|
||||
import com.baeldung.concurrent.threadreturnvalue.task.callable.CallableFactorialTask;
|
||||
|
||||
public class CallableUnitTest {
|
||||
|
||||
private final CallableExecutor callableExecutor = new CallableExecutor();
|
||||
|
||||
@Test
|
||||
void givenCallableExecutor_whenExecuteFactorial_thenResultOk() {
|
||||
BigInteger result = callableExecutor.execute(Arrays.asList(new CallableFactorialTask(5), new CallableFactorialTask(3)));
|
||||
assertEquals(BigInteger.valueOf(126), result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.completableFuture;
|
||||
|
||||
import static com.baeldung.concurrent.threadreturnvalue.task.FactorialCalculator.factorial;
|
||||
import static java.util.concurrent.CompletableFuture.allOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class CompletableFutureUnitTest {
|
||||
|
||||
@Test
|
||||
void givenCompletableFuture_whenSupplyAsyncFactorial_thenResultOk() throws ExecutionException, InterruptedException {
|
||||
CompletableFuture<BigInteger> completableFuture = CompletableFuture.supplyAsync(() -> factorial(BigInteger.valueOf(10)));
|
||||
assertEquals(BigInteger.valueOf(3628800), completableFuture.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCompletableFuture_whenComposeTasks_thenResultOk() throws ExecutionException, InterruptedException {
|
||||
CompletableFuture<BigInteger> completableFuture = CompletableFuture.supplyAsync(() -> factorial(BigInteger.valueOf(3)))
|
||||
.thenCompose(inputFromFirstTask -> CompletableFuture.supplyAsync(() -> factorial(inputFromFirstTask)));
|
||||
assertEquals(BigInteger.valueOf(720), completableFuture.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenCompletableFuture_whenAllOfTasks_thenResultOk() {
|
||||
CompletableFuture<BigInteger> asyncTask1 = CompletableFuture.supplyAsync(() -> BigInteger.valueOf(5));
|
||||
CompletableFuture<String> asyncTask2 = CompletableFuture.supplyAsync(() -> "3");
|
||||
|
||||
BigInteger result = allOf(asyncTask1, asyncTask2).thenApplyAsync(fn -> factorial(asyncTask1.join()).add(factorial(new BigInteger(asyncTask2.join()))), Executors.newFixedThreadPool(1))
|
||||
.join();
|
||||
|
||||
assertEquals(BigInteger.valueOf(126), result);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.concurrent.threadreturnvalue.fork;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.concurrent.threadreturnvalue.task.callable.CallableFactorialTask;
|
||||
import com.baeldung.concurrent.threadreturnvalue.task.fork.ForkExecutor;
|
||||
import com.baeldung.concurrent.threadreturnvalue.task.fork.ForkFactorialTask;
|
||||
|
||||
public class ForkUnitTest {
|
||||
|
||||
private final ForkExecutor forkExecutor = new ForkExecutor();
|
||||
|
||||
@Test
|
||||
void givenForkExecutor_whenExecuteRecursiveTask_thenResultOk() {
|
||||
assertEquals(BigInteger.valueOf(3628800), forkExecutor.execute(new ForkFactorialTask(10, 5)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenForkExecutor_whenExecuteCallable_thenResultOk() {
|
||||
assertEquals(BigInteger.valueOf(126), forkExecutor.execute(Arrays.asList(new CallableFactorialTask(5), new CallableFactorialTask(3))));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue