Select in Java

Java’s concurrency model is different from Go’s, but we can achieve similar functionality using threads and the ExecutorService. Here’s how we can translate the select example:

import java.util.concurrent.*;

public class Select {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // We'll use an ExecutorService to manage our threads
        ExecutorService executor = Executors.newFixedThreadPool(2);

        // For our example we'll select across two futures.
        Future<String> f1 = executor.submit(() -> {
            Thread.sleep(1000);
            return "one";
        });

        Future<String> f2 = executor.submit(() -> {
            Thread.sleep(2000);
            return "two";
        });

        // We'll use CompletableFuture.anyOf to simulate the select behavior
        for (int i = 0; i < 2; i++) {
            CompletableFuture<Object> cf = CompletableFuture.anyOf(
                CompletableFuture.completedFuture(f1),
                CompletableFuture.completedFuture(f2)
            );

            Object result = cf.get();
            if (result == f1) {
                System.out.println("received " + f1.get());
                f1 = CompletableFuture.completedFuture("dummy");
            } else {
                System.out.println("received " + f2.get());
                f2 = CompletableFuture.completedFuture("dummy");
            }
        }

        executor.shutdown();
    }
}

This Java code simulates the behavior of the original example. Here’s a breakdown of what’s happening:

  1. We use an ExecutorService to manage our threads, which is similar to how Go manages goroutines.

  2. Instead of channels, we use Future<String> to represent our asynchronous operations. Each future will complete after a certain amount of time, simulating blocking operations.

  3. We use CompletableFuture.anyOf to wait for either of the futures to complete, which is similar to the select statement in the original code.

  4. We loop twice, each time waiting for one of the futures to complete and then printing its value.

  5. After a future is used, we replace it with a dummy completed future to ensure it’s not selected again.

To run this program, save it as Select.java and use the following commands:

$ javac Select.java
$ java Select
received one
received two

Note that the total execution time will be about 2 seconds, as both the 1-second and 2-second sleeps execute concurrently.

This example demonstrates how to work with concurrent operations in Java, waiting for multiple asynchronous tasks simultaneously. While the syntax and mechanisms are different from the original, the core concept of managing and selecting from multiple concurrent operations remains the same.