import java.util.concurrent.locks.*;

public class TestAwaitAndSignal {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition c1 = lock.newCondition();
        Condition c2 = lock.newCondition();
        Condition c3 = lock.newCondition();
        AwaitThread t1 = new AwaitThread(lock, c1, c2, 1, 3, 50, true);
        AwaitThread t2 = new AwaitThread(lock, c2, c3, 2, 3, 50, false);
        AwaitThread t3 = new AwaitThread(lock, c3, c1, 3, 3, 50, false);
        t1.start();
        t2.start();
        t3.start();
        try {
            Thread.sleep(60);
            lock.lock();
            c1.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

class AwaitThread extends Thread {
    Lock lock;
    Condition curr;
    Condition next;
    int init;
    int delta;
    int count;
    boolean first;

    AwaitThread(Lock lock, Condition curr, Condition next, int init, int delta, int count, boolean first) {
        this.lock = lock;
        this.curr = curr;
        this.next = next;
        this.init = init;
        this.delta = delta;
        this.count = count;
        this.first = first;
    }

    @Override
    public void run() {
        System.out.println("Thread " + init + " is running.");
        for (int i = 0, num = init; i < count; i++) {
            lock.lock();
            try {
                curr.await();
                System.out.println(num);
                num += delta;
                Thread.sleep(5);
                next.signal();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}