1. 使用条件队列

我们可以先创建一个锁对象,使用该锁守护两个线程中的代码块,通过调用锁对象的 wait() 和 notify/notifyAll()来阻塞或唤醒两个线程的执行。

				
					class Solution1 {
    private final Object lock = new Object();

    public static void main(String[] args) {
        new Solution1().print();
    }

    private void print() {
        new Thread(() -> {
            int i = 0;
            while (true) {
                synchronized (lock) {
                    try {
                        System.out.print(i + 1);
                        lock.notify();
                        if (i++ == 2) return;
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        new Thread(() -> {
            int i = 0;
            while (true) {
                synchronized (lock) {
                    try {
                        System.out.print((char) ('A' + i));
                        lock.notify();
                        if (i++ == 2) return;
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}
				
			

2. 使用显式的Condition对象

Condition 是一种广义的内置条件队列,所以该方法与方法1中的实现方式没有本质的区别。

				
					class Solution2 {
    private Lock lock = new ReentrantLock();
    private Condition c1 = lock.newCondition();
    private Condition c2 = lock.newCondition();

    public static void main(String[] args) {
        new Solution2().print();
    }

    private void print() {
        new Thread(() -> {
            int i = 0;
            while (true) {
                lock.lock();
                try {
                    System.out.print(i + 1);
                    c2.signal();
                    if (i++ == 2) return;
                    c1.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }).start();
        new Thread(() -> {
            int i = 0;
            while (true) {
                try {
                    if (i == 0) {
                        TimeUnit.MILLISECONDS.sleep(10);
                    }
                    lock.lock();
                    System.out.print((char) ('A' + i));
                    c1.signal();
                    if (i++ == 2) return;
                    c2.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }).start();
    }
}
				
			

3. 使用信号量

分别定义对应于两个线程的两个信号量 (Semaphore)对象,使用两个信号量的 acquire()和 release() 方法控制线程的阻塞和唤醒。

				
					class Solution3 {
    private Semaphore s1 = new Semaphore(1);
    private Semaphore s2 = new Semaphore(0);

    public static void main(String[] args) {
        new Solution3().print();
    }

    private void print() {
        new Thread(() -> {
            int i = 0;
            while (true) {
                try {
                    s1.acquire();
                    System.out.print(i + 1);
                    s2.release();
                    if (i++ == 2) return;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        new Thread(() -> {
            int i = 0;
            while (true) {
                try {
                    s2.acquire();
                    System.out.print((char) ('A' + i));
                    s1.release();
                    if (i++ == 2) return;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}