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();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)