Channel Synchronization in Karel

Our example demonstrates how to use channels for synchronization between threads in Java. While Java doesn’t have built-in channels like Go, we can simulate this behavior using a BlockingQueue.

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ChannelSynchronization {

    // This is the method we'll run in a separate thread. The
    // BlockingQueue will be used to notify another thread that
    // this method's work is done.
    public static void worker(BlockingQueue<Boolean> done) {
        System.out.print("working...");
        try {
            Thread.sleep(1000);  // Sleep for 1 second
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("done");

        // Send a value to notify that we're done.
        try {
            done.put(true);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // Create a BlockingQueue to simulate a channel
        BlockingQueue<Boolean> done = new LinkedBlockingQueue<>(1);

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

        // Block until we receive a notification from the
        // worker on the queue.
        try {
            done.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

To run this program:

$ javac ChannelSynchronization.java
$ java ChannelSynchronization
working...done

In this Java implementation, we use a BlockingQueue to simulate the channel behavior. The worker method runs in a separate thread and uses Thread.sleep() to simulate work. When it’s done, it puts a true value into the queue.

The main thread starts the worker thread and then waits for a value from the queue using the take() method, which blocks until a value is available.

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

When waiting for multiple threads to finish, you may prefer to use a CountDownLatch or CompletableFuture in Java, which are more idiomatic for this purpose.