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.