java双线程交替打印1-100的数字

第一版代码

Thread threadOdd = new Thread(() -> {
for (int i = 1; i <= 99; i+=2){
synchronized (sharedThing){
System.out.println(Thread.currentThread().getName() + " " + i);
try {
sharedThing.wait();
sharedThing.notify();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});

Thread threadEven = new Thread(() -> {
for (int i = 2; i <= 100; i += 2) {
synchronized (sharedThing) {
System.out.println(Thread.currentThread().getName() + " " + i);
sharedThing.notify();
try {
sharedThing.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
});

threadOdd.start();
Thread.sleep(1000);
threadEven.start();`

image

效果看起来还可以,但是稍微改动一下threadOdd就会出现问题,比如这样:

Thread threadOdd = new Thread(() -> {
for (int i = 1; i <= 99; i+=2){
synchronized (sharedThing){
System.out.println(Thread.currentThread().getName() + " " + i);
try {
sharedThing.wait();
sharedThing.notify();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
结果为:
image

threadOdd抢占共享资源的过程被延长了,导致threadEven先占用了资源,threadOdd无法被唤醒,死锁了

所以修改一下,加入奇数偶数校验,保证打印奇数线程只打印奇数,偶数线程只打印偶数

让两个线程严格按照顺序执行

第二版代码

Thread threadOdd = new Thread(() -> {
while (cur < 100){
synchronized (sharedThing){
if(cur % 2 == 1){
System.out.println(Thread.currentThread().getName() + ":" + cur);
cur += 1;
try {
sharedThing.wait();
sharedThing.notify();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});

Thread threadEven = new Thread(() -> {
while (cur < 100){
synchronized (sharedThing){
if(cur % 2 == 0){
sharedThing.notify();
System.out.println(Thread.currentThread().getName() + ":" + cur);
cur += 1;
try {
sharedThing.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
});

threadOdd.start();
threadEven.start();
}

效果如下

使用ReentrantLock和Condition的代码

奇数线程准备奇数数字1,3,5,... ,49

偶数线程准备偶数数字2,4,6, ... ,50

condition负责保证奇数偶数打印的顺序

public static void reenTrantLockPrint(){
        ReentrantLock reentrantLock = new ReentrantLock();
        Condition oddCondition = reentrantLock.newCondition();
        Condition evenCondition = reentrantLock.newCondition();
        new Thread(() -> {
            int i = 1;
            while(i <= 50){
                reentrantLock.lock();
                if(i % 2 == 1){
                    System.out.println(Thread.currentThread().getName() + " 打印" + i);
                    evenCondition.signal();
                    i+=2;
                    try {
                        oddCondition.await();
                        reentrantLock.unlock();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        },"odd").start();

        new Thread(() -> {
            int i = 2;
            while(i <= 50){
                reentrantLock.lock();
                System.out.println(Thread.currentThread().getName() + " 打印" + i);
                oddCondition.signal();
                i+=2;
                try {
                    evenCondition.await();
                    reentrantLock.unlock();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"even").start();
    }

效果

image

才疏学浅,如果有错误或不准确的地方,欢迎大家指出

posted @ 2025-02-07 15:51  卡利的亲爹  阅读(383)  评论(0)    收藏  举报