Skip to content

Instantly share code, notes, and snippets.

@justADeni
Created June 17, 2025 19:17
Show Gist options
  • Select an option

  • Save justADeni/83cd0fd8f358cb0896cb0bec6d2682fd to your computer and use it in GitHub Desktop.

Select an option

Save justADeni/83cd0fd8f358cb0896cb0bec6d2682fd to your computer and use it in GitHub Desktop.
Utility for launching N amount of threads at the same time and getting a result once the first succeeds or all fail.
public sealed interface Result<T> permits Result.Success, Result.Failure {
record Success<T>(T value) implements Result<T> {}
final class Failure<T> implements Result<T> {}
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
public class VirtualThreadUtil {
public static <T> Result<T> runRace(Supplier<Result<T>> task, int threadCount) {
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
CompletableFuture<Result<T>> result = new CompletableFuture<>();
AtomicInteger remaining = new AtomicInteger(threadCount);
List<Future<?>> futures = new ArrayList<>();
for (int i = 0; i < threadCount; i++) {
Future<?> future = executor.submit(() -> {
if (result.isDone()) return;
Result<T> res = task.get();
if (res instanceof Result.Success<T> success) {
result.complete(success);
} else {
if (remaining.decrementAndGet() == 0 && !result.isDone()) {
result.complete(new Result.Failure<T>());
}
}
});
futures.add(future);
}
try {
return result.get();
} catch (Exception e) {
return new Result.Failure<>();
} finally {
for (Future<?> f : futures) f.cancel(true);
executor.shutdownNow();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment