【LeetCode练习】[中等]1116. 打印零与奇偶数
1116. 打印零与奇偶数
算法思想:多线程
题目:
问题分析
多线程,同步问题;
使用方法:
- 信号量:容易理解,与操作系统中的信号一样,但是效率不高
- 可重用锁:
java代码–信号量
class ZeroEvenOdd {
private int n;
// zero 信号量, 默认可以使用;
private Semaphore zero = new Semaphore(1);
// even 偶数, 不可用
private Semaphore even = new Semaphore(0);
// odd 奇数, 不可用
private Semaphore odd = new Semaphore(0);
public ZeroEvenOdd(int n) {
this.n = n;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i++){
zero.acquire();
printNumber.accept(0);
if (i % 2 == 1){
odd.release(); // 唤醒奇数打印线程
}else {
even.release(); // 唤醒偶数打印线程
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 2; i <= n; i += 2){
even.acquire();
printNumber.accept(i);
zero.release(); // 唤醒 0 打印线程
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i += 2){
odd.acquire();
printNumber.accept(i);
zero.release(); // 唤醒 0 打印线程
}
}
}
java代码–可重入锁,效率更高
容易理解,操作系统中的信号量;但是效率不高,
class ZeroEvenOdd {
private int n;
private volatile int curValue = 0;
// 可重入锁
private Lock lock = new ReentrantLock();
private Condition zero = lock.newCondition();
private Condition even = lock.newCondition();
private Condition odd = lock.newCondition();
public ZeroEvenOdd(int n) {
this.n = n;
}
// printNumber.accept(x) outputs "x", where x is an integer.
public void zero(IntConsumer printNumber) throws InterruptedException {
lock.lock();
try {
for (int i = 1; i <= n ; i++) {
if (curValue != 0){
zero.await();
}
printNumber.accept(0);
if (i % 2 == 1){
curValue = 1;
odd.signal();
}else{
curValue = 2;
even.signal();
}
}
}finally {
lock.unlock();
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
lock.lock();
try {
for (int i = 2; i <= n ; i += 2) {
if (curValue != 2){
even.await();
}
printNumber.accept(i);
curValue = 0;
zero.signal();
}
}finally {
lock.unlock();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
lock.lock();
try {
for (int i = 1; i <= n ; i += 2) {
if (curValue != 1){
odd.await();
}
printNumber.accept(i);
curValue = 0;
zero.signal();
}
}finally {
lock.unlock();
}
}
}