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
相关推荐
karry_k5 小时前
MyBatis批量insert-select踩坑:useGeneratedKeys=true 可能让PostgreSQL返回大量插入结果
java·后端
karry_k6 小时前
PostgreSQL 在 MyBatis 中执行正常 SQL 失效:一次 DELETE USING 踩坑记录
java·后端
SamDeepThinking9 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
她的男孩12 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
荣码14 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python
plainGeekDev15 小时前
Gson → kotlinx.serialization
android·java·kotlin
小bo波1 天前
Java Swing 图形用户界面实验 —— 从算术练习到游戏开发的完整实践
java·课程设计·gui·游戏开发·扫雷·swing
咖啡八杯1 天前
GoF设计模式——备忘录模式
java·后端·spring·设计模式