From 69f6e110880f06e4b8e4ea1c8b39776aec1b31d2 Mon Sep 17 00:00:00 2001 From: Kilian Schneider <48420258+Basler182@users.noreply.github.com> Date: Mon, 23 Jan 2023 21:57:00 +0100 Subject: [PATCH] BAEL-6091 structured concurrency (#13297) --- .../JEP428StructuredConcurrencyUnitTest.java | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java diff --git a/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java b/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java new file mode 100644 index 0000000000..64cd84ba01 --- /dev/null +++ b/core-java-modules/core-java-19/src/test/java/com/baeldung/features/JEP428StructuredConcurrencyUnitTest.java @@ -0,0 +1,122 @@ +package com.baeldung.features; + +import jdk.incubator.concurrent.StructuredTaskScope; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.util.List; +import java.util.concurrent.*; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +public class JEP428StructuredConcurrencyUnitTest { + + private static final String ERROR_MESSAGE = "Failed to get the result"; + + @Test + public void givenStructuredConcurrency_whenThrowingException_thenCorrect() { + assertThatThrownBy(() -> { + try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { + Future shelter = scope.fork(this::getShelter); + Future> dogs = scope.fork(this::getDogsWithException); + scope.throwIfFailed(e -> new RuntimeException(ERROR_MESSAGE)); + scope.join(); + Response response = new Response(shelter.resultNow(), dogs.resultNow()); + + assertThat(response).isNotNull(); + assertThat(response.shelter()).isNotNull(); + assertThat(response.dogs()).isNotNull(); + assertThat(response.dogs().size()).isEqualTo(2); + } + }).isInstanceOf(RuntimeException.class) + .hasMessage(ERROR_MESSAGE); + } + + @Test + public void givenStructuredConcurrency_whenSlowTasksReachesDeadline_thenCorrect() { + assertThatThrownBy(() -> { + try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { + Future shelter = scope.fork(this::getShelter); + Future> dogs = scope.fork(this::getDogsSlowly); + scope.throwIfFailed(e -> new RuntimeException(ERROR_MESSAGE)); + scope.join(); + scope.joinUntil(Instant.now().plusMillis(50)); + Response response = new Response(shelter.resultNow(), dogs.resultNow()); + + assertThat(response).isNotNull(); + assertThat(response.shelter()).isNotNull(); + assertThat(response.dogs()).isNotNull(); + assertThat(response.dogs().size()).isEqualTo(2); + + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }).isInstanceOf(IllegalStateException.class); + } + + @Test + public void givenStructuredConcurrency_whenResultNow_thenCorrect() { + try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { + Future shelter = scope.fork(this::getShelter); + Future> dogs = scope.fork(this::getDogs); + scope.join(); + + Response response = new Response(shelter.resultNow(), dogs.resultNow()); + + assertThat(response).isNotNull(); + assertThat(response.shelter()).isNotNull(); + assertThat(response.dogs()).isNotNull(); + assertThat(response.dogs().size()).isEqualTo(2); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Test + public void givenUnstructuredConcurrency_whenGet_thenCorrect() { + Future shelter; + Future> dogs; + try (ExecutorService executorService = Executors.newFixedThreadPool(3)) { + shelter = executorService.submit(this::getShelter); + dogs = executorService.submit(this::getDogs); + Shelter theShelter = shelter.get(); // Join the shelter + List theDogs = dogs.get(); // Join the dogs + Response response = new Response(theShelter, theDogs); + + assertThat(response).isNotNull(); + assertThat(response.shelter()).isNotNull(); + assertThat(response.dogs()).isNotNull(); + assertThat(response.dogs().size()).isEqualTo(2); + + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + private Shelter getShelter() { + return new Shelter("Shelter"); + } + + private List getDogs() { + return List.of(new Dog("Buddy"), new Dog("Simba")); + } + + private List getDogsWithException() { + throw new RuntimeException(ERROR_MESSAGE); + } + + private List getDogsSlowly() throws InterruptedException { + Thread.sleep(1500); + throw new RuntimeException(ERROR_MESSAGE); + } + + record Shelter(String name) { + } + + record Dog(String name) { + } + + record Response(Shelter shelter, List dogs) { + } +} \ No newline at end of file