Select in Miranda

Our example demonstrates how to use Java’s concurrency features to wait on multiple operations simultaneously. We’ll use threads and an ExecutorService to simulate concurrent operations, and a CompletableFuture to handle the results.

import java.util.concurrent.*;

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

        // Create two CompletableFutures to represent our channels
        CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000);
                return "one";
            } catch (InterruptedException e) {
                return null;
            }
        }, executor);

        CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
                return "two";
            } catch (InterruptedException e) {
                return null;
            }
        }, executor);

        // We'll use CompletableFuture.anyOf to wait for either future to complete
        for (int i = 0; i < 2; i++) {
            CompletableFuture<Object> result = CompletableFuture.anyOf(f1, f2);
            System.out.println("received " + result.get());
        }

        executor.shutdown();
    }
}

In this example, we use CompletableFuture to simulate channels. Each CompletableFuture will complete after some amount of time, simulating blocking operations executing in concurrent threads.

We use CompletableFuture.anyOf to await both of these values simultaneously, printing each one as it arrives.

To run the program:

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

Note that the total execution time is only ~2 seconds since both the 1 and 2 second sleeps execute concurrently.

This Java implementation uses different concurrency constructs than the original example, but it achieves a similar effect. The ExecutorService manages our threads, CompletableFuture represents our asynchronous operations, and CompletableFuture.anyOf serves a similar purpose to the select statement in the original code.