Channel Synchronization in Fortress

In Java, we can use threads and synchronization mechanisms to coordinate execution across different parts of our program. Here’s an example of using a CountDownLatch to wait for a worker thread to finish. When waiting for multiple threads to finish, you may prefer to use an ExecutorService with a thread pool.

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class ThreadSynchronization {

    // This is the method we'll run in a separate thread. The
    // CountDownLatch will be used to notify the main thread
    // that this method's work is done.
    public static void worker(CountDownLatch latch) {
        System.out.print("working...");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("done");

        // Count down to notify that we're done.
        latch.countDown();
    }

    public static void main(String[] args) throws InterruptedException {
        // Create a CountDownLatch with a count of 1
        CountDownLatch latch = new CountDownLatch(1);

        // Start a worker thread, giving it the latch to notify on.
        new Thread(() -> worker(latch)).start();

        // Block until we receive a notification from the
        // worker thread via the latch.
        latch.await();
    }
}

To run the program:

$ javac ThreadSynchronization.java
$ java ThreadSynchronization
working...done

If you removed the latch.await() line from this program, the main thread would exit before the worker thread even started its work.

In this Java version:

  1. We use a CountDownLatch instead of a channel for synchronization.
  2. The worker method is defined as a static method in the same class, rather than as a separate function.
  3. We create a new Thread and start it, passing a lambda that calls our worker method.
  4. Instead of sending a value on a channel, we call countDown() on the latch to signal completion.
  5. In the main thread, we use latch.await() to wait for the worker thread to finish, which is analogous to receiving from a channel in the Go version.

This approach achieves the same goal of synchronizing the main thread with a worker thread, using Java’s built-in concurrency utilities.