Closing Channels in Logo
In Java, we don’t have built-in channels like in some other languages. However, we can simulate similar behavior using BlockingQueue
from the java.util.concurrent
package. We’ll use ArrayBlockingQueue
for this example.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ClosingChannels {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Integer> jobs = new ArrayBlockingQueue<>(5);
BlockingQueue<Boolean> done = new ArrayBlockingQueue<>(1);
// Here's the worker thread. It repeatedly takes from 'jobs'.
// We use a special value (null) to indicate that no more jobs will be sent.
Thread worker = new Thread(() -> {
while (true) {
try {
Integer j = jobs.take();
if (j != null) {
System.out.println("received job " + j);
} else {
System.out.println("received all jobs");
done.put(true);
return;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
});
worker.start();
// This sends 3 jobs to the worker over the 'jobs' queue,
// then sends a null to indicate no more jobs.
for (int j = 1; j <= 3; j++) {
jobs.put(j);
System.out.println("sent job " + j);
}
jobs.put(null);
System.out.println("sent all jobs");
// We await the worker using the synchronization approach.
done.take();
// After closing, any attempt to take from the queue will return null immediately.
Integer j = jobs.poll();
System.out.println("received more jobs: " + (j != null));
}
}
In this example, we use ArrayBlockingQueue
to simulate channels. The BlockingQueue
interface provides methods that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
We create a worker thread that continuously takes jobs from the jobs
queue. To signal that no more jobs will be sent, we send a null
value, which the worker interprets as a signal to finish.
The main thread sends three jobs to the worker, then sends a null
to indicate it’s finished. It then waits for the worker to signal completion by taking from the done
queue.
After the worker has finished, we attempt to take another job from the jobs
queue. Since the queue is empty (and we’re using poll()
which doesn’t block), this returns null
immediately.
To run this program:
$ javac ClosingChannels.java
$ java ClosingChannels
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
received more jobs: false
This example demonstrates how to simulate channel-like behavior in Java using BlockingQueue
. While it’s not identical to channel closing in some other languages, it achieves a similar effect of signaling completion to a worker thread.