StructuredExecutor Incompatible with HttpClient?

Eric Kolotyluk eric at kolotyluk.net
Sun Nov 28 19:19:20 UTC 2021


package net.kolotyluk.loom;

import java.net.http.HttpResponse;
import java.time.Duration;

import java.time.Instant;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.URI;

public class Experiment20_HttpClient {

    public static void main2(String args[]) {
        Context.printHeader(Experiment20_HttpClient.class);

        var virtualThreadFactory  = Thread.ofVirtual().factory();

        try (var executorService =
Executors.newThreadPerTaskExecutor(virtualThreadFactory)) {

            // https://apipheny.io/free-api/

            var client = HttpClient.newBuilder()
                    .executor(executorService)
                    .connectTimeout(Duration.ofSeconds(10))
                    .build();

            var request = HttpRequest.newBuilder()
                    .uri(URI.create("https://www.boredapi.com/api/activity"))
                    .build();

            Callable<String> getActivity = () -> {
                var response = client.sendAsync(request,
HttpResponse.BodyHandlers.ofString())
                        .thenApply(HttpResponse::body)
                        .join();
                System.out.printf("early result = %s\n", response);
                return response;
            };

            var result1 = executorService.submit(getActivity);

            System.out.printf("result1 = %s", result1.get());
        }
        catch (ExecutionException e) {
            e.printStackTrace();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        Context.printHeader(Experiment20_HttpClient.class);

        try (var structuredExecutor = StructuredExecutor.open("Experiment20")) {

            // https://apipheny.io/free-api/

            var client = HttpClient.newBuilder()
                    .executor(structuredExecutor)
                    .connectTimeout(Duration.ofSeconds(10))
                    .build();

            var request = HttpRequest.newBuilder()
                    .uri(URI.create("https://www.boredapi.com/api/activity"))
                    .build();

            Callable<String> getActivity = () -> {
                var response = client.sendAsync(request,
HttpResponse.BodyHandlers.ofString())
                        .thenApply(HttpResponse::body)
                        .join();
                System.out.printf("early result = %s\n", response);
                return response;
            };

            var result1 = structuredExecutor.fork(getActivity);

            try {
                structuredExecutor.joinUntil(Instant.now().plusSeconds(10));
            }
            catch (TimeoutException e) {
                System.out.println("TimeoutException");
                structuredExecutor.shutdown();
                // structuredExecutor.join();
                System.out.printf("result = %s", result1.resultNow());
            }

            System.out.printf("result1 = %s", result1.get());
        }
        catch (ExecutionException e) {
            e.printStackTrace();
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

So, main2 seems to work as expected, but main does not

Hello net.kolotyluk.loom.Experiment20_HttpClient
PID       = 35712
CPU Cores = 12
Heap Size = 6442450944 bytes
______________________________________________________________________________

TimeoutException

Process finished with exit code 130

It hangs indefinitely after TimeoutException, and I have to manually kill
it. The correct output should be

Hello net.kolotyluk.loom.Experiment20_HttpClient
PID       = 3480
CPU Cores = 12
Heap Size = 6442450944 bytes
______________________________________________________________________________

early result = {"activity":"Clean out your closet and donate the clothes
you've
outgrown","type":"charity","participants":1,"price":0,"link":"","key":"9026787","accessibility":0.1}
result1 = {"activity":"Clean out your closet and donate the clothes you've
outgrown","type":"charity","participants":1,"price":0,"link":"","key":"9026787","accessibility":0.1}
Process finished with exit code 0

Cheers, Eric


More information about the loom-dev mailing list