Two java solutions: wait + notify + volatile and lock + condition
Wait + notify + volatile\n \n\nclass ZeroEvenOdd {\n\n    private int n;\n\n    private final int ZERO = 0;\n    private final int EVEN = 1;\n    private final 
Wait + notify + volatile\n \n```\nclass ZeroEvenOdd {\n\n    private int n;\n\n    private final int ZERO = 0;\n    private final int EVEN = 1;\n    private final int ODD = 2;\n\n    private volatile int state = ZERO;\n\n    public ZeroEvenOdd(int n) {\n        this.n = n;\n    }\n\n    public synchronized void zero(IntConsumer printNumber) throws InterruptedException {\n        for (int i = 0; i < n; i++) {\n            while (state != ZERO) wait();\n\n            printNumber.accept(0);\n            if (i % 2 == 0) {\n                state = ODD;\n            } else {\n                state = EVEN;\n            }\n            notifyAll();\n        }\n    }\n\n    public synchronized void even(IntConsumer printNumber) throws InterruptedException {\n        for (int i = 2; i <= n; i += 2) {\n            while (state != EVEN) wait();\n            printNumber.accept(i);\n            state = ZERO;\n            notifyAll();\n        }\n    }\n\n    public synchronized void odd(IntConsumer printNumber) throws InterruptedException {\n        for (int i = 1; i <= n; i += 2) {\n            while (state != ODD) wait();\n\n            printNumber.accept(i);\n            state = ZERO;\n            notifyAll();\n        }\n    }\n}\n```\n\nLock + condition\n\n```\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\nimport java.util.function.IntConsumer;\n\npublic class ZeroEvenOdd {\n    private int n;\n\t\n    private final int ZERO = 0;\n    private final int EVEN = 1;\n    private final int ODD = 2;\n\n    private volatile int state = ZERO;\n    \n    private Lock lock = new ReentrantLock();\n    private Condition zero = lock.newCondition();\n    private Condition even = lock.newCondition();\n    private Condition odd = lock.newCondition();\n\n    public ZeroEvenOdd(int n) {\n        this.n = n;\n    }\n\n    public void zero(IntConsumer printNumber) throws InterruptedException {\n        for (int i = 0; i < n; i++) {\n            lock.lock();\n            try {\n                if (state != ZERO) {\n                    zero.await();\n                }\n                printNumber.accept(0);\n                if (i % 2 == 0) {\n                    state = ODD;\n                    odd.signal();\n                } else {\n                    state = EVEN;\n                    even.signal();\n                }\n            } finally {\n                lock.unlock();\n            }\n        }\n    }\n\t\n    public void even(IntConsumer printNumber) throws InterruptedException {\n        for (int i = 2; i <= n; i += 2) {\n            lock.lock();\n            try {\n                if (state != EVEN) {\n                    even.await();\n                }\n                state = ZERO;\n                printNumber.accept(i);\n                zero.signal();\n            } finally {\n                lock.unlock();\n            }\n        }\n    }\n\n    public void odd(IntConsumer printNumber) throws InterruptedException {\n        for (int i = 1; i <= n; i += 2) {\n            lock.lock();\n            try {\n                if (state != ODD) {\n                    odd.await();\n                }\n                state = ZERO;\n                printNumber.accept(i);\n                zero.signal();\n            } finally {\n                lock.unlock();\n            }\n        }\n    }\n}\n```
[]