看到一题目“多线程按顺序打印奇偶数”,网上的做法是通过synchronized,wait,notify来实现,其实现存在bug,奇偶线程需按顺序启动,不然打印的数不正确。我通过lock和condition也实现了一个,做到可以启动多个奇数线程和多个偶数线程也能按一定的顺序打印。
public static void main(String[] args) {
final NumberPrinter numberPrinter = new NumberPrinter();
Thread t1 = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
numberPrinter.printNum(true);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread t2 = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
numberPrinter.printNum(false);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread t3 = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
numberPrinter.printNum(false);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
t1.start();
t2.start();
t3.start();
try {
Thread.sleep(9000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.interrupt();
t2.interrupt();
t3.interrupt();
}
class NumberPrinter {
private final Lock lock = new ReentrantLock();
private final Condition oddNumCon = lock.newCondition();
private final Condition eventNumCon = lock.newCondition();
private volatile int num = 0;
public void printNum(boolean isOddNum) throws InterruptedException {
lock.lock();
try {
if (isOddNum) {
while (num % 2 == 0) {
//奇数等待
oddNumCon.await();
}
} else {
while (num % 2 == 1) {
//偶数等待
eventNumCon.await();
}
}
Thread.sleep(500L);
System.out.println(Thread.currentThread().getName() + " say:" + num++);
if (isOddNum) {
//唤醒偶数
eventNumCon.signal();
} else {
//唤醒奇数
oddNumCon.signal();
}
} finally {
lock.unlock();
}
}
}
网友评论