Skip to content

线程交替执行

今天面试的问题,面试官需要我实现多线程交替去打印1-100,查了一下之后发现这是一道面试中常考的并发编程的代码题,与它相似的问题有:

  • 三个线程T1、T2、T3轮流打印ABC,打印n次,如ABCABCABCABC.......
  • 两个线程交替打印1-100的奇偶数
  • N个线程循环打印1-100
  • ......

其实这类问题本质上都是线程通信问题,思路基本上都是一个线程执行完毕,阻塞该线程,唤醒其他线程,按顺序执行下一个线程。

首先通过锁来控制只有一个线程可以获得资源,再通过notify方法去唤醒别的线程,要注意的是notify方法不会立刻唤醒,而是等待锁被释放了才唤醒。

代码

java
public class Main {
    private static final int MAX_COUNT = 100;
    private static volatile int count = 1;
    private static final Object lock = new Object();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new PrintTask());
            thread.start();
        }
    }

    static class PrintTask implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (lock) {
                    // 检查是否已经打印完毕
                    if (count > MAX_COUNT) {
                        lock.notifyAll();
                        break;
                    }
                    System.out.println(count);
                    count ++;
                    lock.notifyAll();
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}

问题

在写的第一版里发现打印完数据之后,程序不结束。发现问题是出在当某个线程在数据打印完毕后直接跳出循环了,没有唤醒。即当所有线程都等待在lock.wait()处时,没有线程来唤醒它们。这会导致所有线程陷入无限等待,导致程序不会结束。

修改就是当线程打印完毕所有的数字后先唤醒,再跳出循环。