Java中两个线程交替打印1-100

方式1:使用synchronized和wait()/notify()

java 复制代码
public class AlternatePrint {
    private int number = 1;
    private final Object lock = new Object();
    
    public void printOddEven() {
        // 奇数线程
        Thread thread1 = new Thread(() -> {
            synchronized (lock) {
                while (number <= 100) {
                    if (number % 2 == 1) {  // 打印奇数
                        System.out.println(Thread.currentThread().getName() + ": " + number++);
                        lock.notify();
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                lock.notify();  // 唤醒可能还在等待的线程
            }
        }, "奇数线程");
        
        // 偶数线程
        Thread thread2 = new Thread(() -> {
            synchronized (lock) {
                while (number <= 100) {
                    if (number % 2 == 0) {  // 打印偶数
                        System.out.println(Thread.currentThread().getName() + ": " + number++);
                        lock.notify();
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                lock.notify();  // 唤醒可能还在等待的线程
            }
        }, "偶数线程");
        
        thread1.start();
        thread2.start();
    }
    
    public static void main(String[] args) {
        new AlternatePrint().printOddEven();
    }
}

方式2:使用ReentrantLock和Condition(更灵活)

java 复制代码
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AlternatePrintWithLock {
    private int number = 1;
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition oddCondition = lock.newCondition();  // 奇数条件
    private final Condition evenCondition = lock.newCondition(); // 偶数条件
    
    public void printOddEven() {
        // 打印奇数
        Thread oddThread = new Thread(() -> {
            lock.lock();
            try {
                while (number <= 100) {
                    if (number % 2 == 1) {
                        System.out.println("奇数线程: " + number++);
                        evenCondition.signal();  // 唤醒偶数线程
                    } else {
                        oddCondition.await();    // 等待
                    }
                }
                evenCondition.signal();  // 最后唤醒偶数线程,防止死锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        
        // 打印偶数
        Thread evenThread = new Thread(() -> {
            lock.lock();
            try {
                while (number <= 100) {
                    if (number % 2 == 0) {
                        System.out.println("偶数线程: " + number++);
                        oddCondition.signal();   // 唤醒奇数线程
                    } else {
                        evenCondition.await();   // 等待
                    }
                }
                oddCondition.signal();  // 最后唤醒奇数线程,防止死锁
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        });
        
        oddThread.start();
        evenThread.start();
    }
    
    public static void main(String[] args) {
        new AlternatePrintWithLock().printOddEven();
    }
}

方式3:使用AtomicInteger和Semaphore(更简洁)

java 复制代码
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

public class AlternatePrintWithSemaphore {
    private AtomicInteger number = new AtomicInteger(1);
    private Semaphore oddSemaphore = new Semaphore(1);   // 奇数信号量,初始有许可
    private Semaphore evenSemaphore = new Semaphore(0);  // 偶数信号量,初始无许可
    
    public void printOddEven() {
        // 打印奇数
        Thread oddThread = new Thread(() -> {
            while (number.get() <= 100) {
                try {
                    oddSemaphore.acquire();  // 获取奇数信号量
                    if (number.get() <= 100) {
                        System.out.println("奇数线程: " + number.getAndIncrement());
                    }
                    evenSemaphore.release(); // 释放偶数信号量
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        // 打印偶数
        Thread evenThread = new Thread(() -> {
            while (number.get() <= 100) {
                try {
                    evenSemaphore.acquire();  // 获取偶数信号量
                    if (number.get() <= 100) {
                        System.out.println("偶数线程: " + number.getAndIncrement());
                    }
                    oddSemaphore.release();   // 释放奇数信号量
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
        oddThread.start();
        evenThread.start();
    }
    
    public static void main(String[] args) {
        new AlternatePrintWithSemaphore().printOddEven();
    }
}

方式4:通用模板类(可复用)

java 复制代码
public class AlternatePrintTemplate {
    private int num = 1;
    private final Object lock = new Object();
    
    public void alternatePrint(int max) {
        new Thread(() -> printNum(max, 1), "线程A").start();
        new Thread(() -> printNum(max, 0), "线程B").start();
    }
    
    private void printNum(int max, int remainder) {
        synchronized (lock) {
            while (num <= max) {
                // 使用位运算判断奇偶,性能更好
                if ((num & 1) == remainder) {
                    System.out.println(Thread.currentThread().getName() + ": " + num++);
                    lock.notifyAll();
                } else {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
    }
    
    public static void main(String[] args) {
        new AlternatePrintTemplate().alternatePrint(100);
    }
}

关键点说明:

  1. 线程同步:必须确保两个线程不会同时操作共享变量

  2. 线程通信:需要正确使用wait/notify或Condition进行线程间通信

  3. 边界条件:正确处理打印到100后两个线程都能正常退出

  4. 避免死锁:确保即使一个线程先结束,另一个线程也不会永久等待

推荐:

  • 对于简单场景,推荐使用方式1(synchronized)

  • 对于需要更精细控制的情况,推荐方式2(ReentrantLock)

  • 对于性能要求高的场景,推荐使用方式4的位运算判断奇偶

这些方法都能实现两个线程交替打印1-100,输出结果类似于:

java 复制代码
奇数线程: 1
偶数线程: 2
奇数线程: 3
偶数线程: 4
...
奇数线程: 99
偶数线程: 100
相关推荐
520拼好饭被践踏5 分钟前
JAVA+Agent学习day22
java·开发语言·后端·学习
笨蛋不要掉眼泪17 分钟前
Java虚拟机:堆的参数配置
java·开发语言·jvm
霸道流氓气质19 分钟前
SpringBoot中使用JasperReports 报表引擎 — 介绍、原理与使用实践
java·spring boot·后端
冰暮流星22 分钟前
javascript之date对象
开发语言·javascript·ecmascript
花生了什么事o24 分钟前
DDD 分层架构:六层分层架构
java·架构·ddd
Y38153266227 分钟前
3 种 SERP 数据处理方案对比:流式 / 批处理 / 缓存
java·spring·缓存
Wang's Blog1 小时前
Go-Zero项目开发17: IM私聊功能实现与消息存储设计
开发语言·后端·golang
Ulyanov1 小时前
Python雷达电子对抗仿真引擎(一):打破单体瓶颈,构建微服务与ECS架构的顶层设计
开发语言·python·微服务·云原生·架构·雷达电子对抗
IT方大同1 小时前
C语言分支与循环语句
c语言·开发语言·算法
qq_150841991 小时前
SQL的insert和update二合一指令
java·数据库·sql