Java多线程实现:3线程存整数、过滤奇偶的代码开发求助
我来帮你完善这个多线程整数分类的Java程序!你的需求是三个线程协作:一个生产整数,另外两个分别筛选偶数和奇数存入对应列表。这里核心要解决线程安全和线程间协作的问题,我给你写了完整的可运行代码,同时拆解关键细节:
import java.util.LinkedList; public class Manage { private final Object lock = new Object(); private final LinkedList<Integer> intStorage = new LinkedList<>(); private final LinkedList<Integer> evens = new LinkedList<>(); private final LinkedList<Integer> odds = new LinkedList<>(); // 标记生产线程是否完成任务,volatile保证多线程可见性 private volatile boolean isProducingDone = false; // 生产线程:往intStorage存入整数 public void intCollection() throws InterruptedException { try { // 这里模拟生产1-100的整数,你可以根据需求修改范围 for (int i = 1; i <= 100; i++) { synchronized (lock) { intStorage.add(i); System.out.println("生产线程存入:" + i); // 通知等待的筛选线程有新数据了 lock.notifyAll(); } // 模拟生产间隔,让多线程协作效果更直观 Thread.sleep(50); } } finally { synchronized (lock) { isProducingDone = true; // 通知所有筛选线程生产已结束,不用再等待 lock.notifyAll(); } } } // 筛选偶数的线程 public void filterEvens() throws InterruptedException { synchronized (lock) { while (true) { // 当存储列表为空且生产未完成时,进入等待 while (intStorage.isEmpty() && !isProducingDone) { lock.wait(); } // 生产完成且列表为空,退出循环结束线程 if (intStorage.isEmpty() && isProducingDone) { break; } // 取出第一个元素判断是否为偶数 Integer num = intStorage.removeFirst(); if (num % 2 == 0) { evens.add(num); System.out.println("偶数线程存入:" + num); } else { // 是奇数就放回列表,让奇数线程处理 intStorage.addFirst(num); // 通知奇数线程有数据待处理 lock.notifyAll(); } } } } // 筛选奇数的线程 public void filterOdds() throws InterruptedException { synchronized (lock) { while (true) { // 当存储列表为空且生产未完成时,进入等待 while (intStorage.isEmpty() && !isProducingDone) { lock.wait(); } // 生产完成且列表为空,退出循环结束线程 if (intStorage.isEmpty() && isProducingDone) { break; } // 取出第一个元素判断是否为奇数 Integer num = intStorage.removeFirst(); if (num % 2 != 0) { odds.add(num); System.out.println("奇数线程存入:" + num); } else { // 是偶数就放回列表,让偶数线程处理 intStorage.addFirst(num); // 通知偶数线程有数据待处理 lock.notifyAll(); } } } } public static void main(String[] args) throws InterruptedException { Manage manager = new Manage(); // 创建并启动三个线程 Thread producer = new Thread(() -> { try { manager.intCollection(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("生产线程被中断"); } }); Thread evenFilter = new Thread(() -> { try { manager.filterEvens(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("偶数线程被中断"); } }); Thread oddFilter = new Thread(() -> { try { manager.filterOdds(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("奇数线程被中断"); } }); producer.start(); evenFilter.start(); oddFilter.start(); // 等待所有线程执行完毕 producer.join(); evenFilter.join(); oddFilter.join(); // 输出最终分类结果 System.out.println("\n最终偶数列表:" + manager.evens); System.out.println("最终奇数列表:" + manager.odds); } }
关键细节拆解
- 线程安全保障:所有操作共享列表的代码都包裹在
synchronized (lock)块中,确保同一时间只有一个线程能修改或访问这些列表,避免竞态条件导致的数据混乱。 - 等待/通知机制:
- 筛选线程在存储列表为空且生产未完成时,调用
lock.wait()进入等待状态,避免空轮询浪费CPU资源。 - 生产线程每次存入数据后,调用
lock.notifyAll()唤醒所有等待的筛选线程;生产完成后再次通知,让筛选线程知道可以退出。
- 筛选线程在存储列表为空且生产未完成时,调用
- 非目标数据处理:比如偶数线程取出奇数时,会把数据放回存储列表头部,并通知其他线程,确保每个数据都能被正确分类。
- 中断处理:每个线程都捕获了
InterruptedException并重置中断状态,符合Java线程中断的最佳实践。 - volatile关键字:
isProducingDone用volatile修饰,保证生产线程修改这个状态后,其他线程能立刻看到最新值,不会出现线程无限等待的情况。
内容的提问来源于stack exchange,提问作者user9679684
相关产品推荐
相关产品推荐

