Last active
March 15, 2020 13:12
-
-
Save pedrominicz/822a421c41f0b42410f235839468a15c to your computer and use it in GitHub Desktop.
Producer-Consumer example in Java.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.LinkedList; | |
import java.util.Queue; | |
public class Consumer { | |
public static void main(final String[] args) { | |
// `Channel` is a singleton class defined below. | |
final Channel channel = Channel.INSTANCE; | |
// Producer thread. The only noticeable curiosity about it is that is | |
// makes use of anonymous classes. | |
new Thread(new Runnable() { | |
@Override | |
public void run() { | |
for (int i = 0; true; ++i) { | |
try { | |
channel.send(i); | |
// `Thread::sleep` may throw `InterruptedException` | |
// which must be caught. | |
Thread.sleep(1000); | |
} catch (InterruptedException ie) { | |
// Empty. | |
} | |
} | |
} | |
}).start(); | |
// Consumer thread. | |
new Thread(new Runnable() { | |
@Override | |
public void run() { | |
while (true) { | |
try { | |
// `Channel::receive` may throw `InterruptedException` | |
// which must be caught. | |
System.out.println(channel.receive()); | |
} catch (InterruptedException ie) { | |
// Empty. | |
} | |
} | |
} | |
}).start(); | |
} | |
// Singleton class representing an integer channel. This is a singleton | |
// class and not just a bunch of static methods because it uses | |
// `Object::notify` and `Object::wait`. | |
private static class Channel { | |
public static final Channel INSTANCE = new Channel(); | |
private static final Queue<Integer> queue = new LinkedList<Integer>(); | |
// `synchronized` enforces that only one thread accesses this function | |
// at any given time. `synchronized` works on a per object basis, | |
// however `Channel` is a singleton class. | |
public synchronized void send(final int i) { | |
queue.add(i); | |
// Notify waiting thread. There is no point calling | |
// `Object::notifyAll` because the first thread to wake-up will | |
// empty the queue. | |
notify(); | |
} | |
public synchronized int receive() throws InterruptedException { | |
if (queue.size() == 0) { | |
// Forces current thread to wait until `Object::notify` or | |
// `Object::notifyAll` is called in another thread. | |
// | |
// Note that `Object::wait` may throw `InterruptedException`. | |
wait(); | |
} | |
return queue.remove(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment