线程交替执行
今天面试的问题,面试官需要我实现多线程交替去打印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()
处时,没有线程来唤醒它们。这会导致所有线程陷入无限等待,导致程序不会结束。
修改就是当线程打印完毕所有的数字后先唤醒,再跳出循环。