如何使用两个线程交替打印奇偶数?
这是一道经典的面试题,与生产消费者模型类似,都是在使用锁控制两个线程的线程安全问题。
先看代码:
public class OddEvenPrinter {
private final Object monitor = new Object();
private final int limit;
private volatile int count;
public OddEvenPrinter(int limit, int initCount) {
this.limit = limit;
this.count = initCount;
}
public void print() {
synchronized (monitor) {
while (count < limit) {
try {
System.out.println(String.format("线程[%s]打印数字:%d", Thread.currentThread().getName(), ++count));
monitor.notify();
if (count < limit) {
monitor.wait();
}
} catch (InterruptedException e) {
//ignore
}
}
}
}
public static void main(String[] args) throws Exception {
OddEvenPrinter printer = new OddEvenPrinter(100, 0);
Thread thread1 = new Thread(printer::print, "thread-1");
Thread thread2 = new Thread(printer::print, "thread-2");
thread1.start();
thread2.start();
}
}
代码不长,主要启动两个线程然后开始打印数字,这里面有两个重点的 API,也是现学的, 分别是 notify 和 wait。
monitor.notify() 会通知某一个在等待 monitor 对象锁的线程,准备获取锁然后执行代码。直到当前线程执行 monitor.wait() 或者执行完成,另一个线程就能继续执行了。
当然正常情况下一个线程进入了 synchronized (monitor) 代码段,直到走出 synchronized 否则别的线程是获取不到 monitor 对象锁的。而 monitor.wait() 会释放 monitor 锁,所以与 monitor.notify() 配合使用,就能切换当前执行的线程,从而实现交替打印奇偶数。
by 费城的二鹏 2020.07.24 长春