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();`

效果看起来还可以,但是稍微改动一下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);
}
}
});
结果为:

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();
}
效果


浙公网安备 33010602011771号