H2O
import java.util.*; import java.util.concurrent.locks.*; public class H2O { private int HCount = 0; private int OCount = 0; private Lock lock = new ReentrantLock(); private Condition condH = lock.newCondition(); private Condition condO = lock.newCondition(); public void H() throws InterruptedException{ lock.lock(); try { HCount++; if (HCount >= 2 && OCount >= 1) { System.out.println("2 H and 1 O consumed in H()"); HCount -= 2; OCount -= 1; condH.signal(); condO.signal(); } else { condH.await(); } } finally { lock.unlock(); } } public void O() throws InterruptedException{ lock.lock(); try { OCount++; if (HCount >= 2 && OCount >= 1) { System.out.println("2 H and 1 O consumed in O()"); HCount -= 2; OCount -= 1; condH.signal(); condH.signal(); } else { condO.await(); } } finally { lock.unlock(); } } public static void main(String[] args) { int n = 3; final H2O h2o = new H2O(); Thread[] threads = new Thread[n]; for (int i=0; i<n; i++) { final int id = i; threads[i] = new Thread(new Runnable() { @Override public void run() { for (int j=0; j<3; j++) { if (id %3 == 0) { try { System.out.println(String.format("Producing an O in thread %d", id)); h2o.O(); } catch (InterruptedException e) { System.out.println(String.format("Thread %d is interrupted for O().", id)); } } else { try { System.out.println(String.format("Producing an H in thread %d", id)); h2o.H(); } catch (InterruptedException e) { System.out.println(String.format("Thread %d is interrupted for H().", id)); } } } } }); } for (Thread thread : threads) { thread.start(); } } }