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
相关推荐
2601_9620715710 小时前
【Java报错已解决】org.springframework.beans.factory.BeanCreationException
java·开发语言
zww894911110 小时前
酒馆预约系统开发实战:从需求分析到上线全流程指南
java·eclipse
淡海水11 小时前
07-04-并发-ConcurrentBag-T-工作窃取WorkStealing算法
开发语言·算法·c#·bag·concurrent·workstealing
CS_Zero11 小时前
C语言sizeof是函数吗?
c语言·开发语言
-今昭-12 小时前
《V2V 迁移实战:将 VMware 虚拟机转为 OpenStack 可用 Glance qcow2 镜像》
开发语言·python
zww894911113 小时前
匿名树洞系统开发实战:从需求分析到部署指南
java·eclipse
黑马程序员毕设14 小时前
基于Java的医院药品管理系统的优化设计与实现
java·开发语言·spring boot·小程序·架构·课程设计·毕设
木井巳14 小时前
【BFS/DFS 解决 FloodFill 算法】太平洋大西洋水流问题
java·算法·leetcode·深度优先·广度优先·宽度优先·推荐算法
白山编程大哥15 小时前
Java 集合算法:从排序、查找到底层原理的实战指南
java·python·算法
_Twink1e15 小时前
openJiuwen 实训营 Day 1 · WorkSwarm 入门教程
开发语言·c++·openjiuwen