You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java双线程生成有序奇偶数字:输出无序且不完整问题

问题分析与修复方案

核心问题

  1. 主线程提前打印列表:主线程启动工作线程后立刻输出列表,此时线程尚未执行完毕,导致输出不完整甚至为空。
  2. 同步逻辑缺陷:
    • 奇数线程添加元素后进入等待,但偶数线程循环结束后未触发最后一次通知,会导致奇数线程永久阻塞。
    • 现有逻辑无法保证严格的数字顺序,比如奇数线程先启动会先添加1,再等待偶数线程添加0,造成顺序混乱。

修复后的完整代码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Odd implements Runnable {
    private final int number;
    private final List<Integer> allNumber;

    public Odd(int number, List<Integer> allNumber) {
        this.number = number;
        this.allNumber = allNumber;
    }

    @Override
    public void run() {
        synchronized (allNumber) {
            for (int i = 1; i <= number; i += 2) {
                // 等待偶数线程完成前一次添加,保证顺序
                while (allNumber.size() % 2 != 0) {
                    try {
                        allNumber.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
                allNumber.add(i);
                allNumber.notify();
            }
        }
    }
}

class Even implements Runnable {
    private final int number;
    private final List<Integer> allNumber;

    public Even(int number, List<Integer> allNumber) {
        this.number = number;
        this.allNumber = allNumber;
    }

    @Override
    public void run() {
        synchronized (allNumber) {
            for (int i = 0; i <= number; i += 2) {
                // 等待奇数线程完成前一次添加,保证顺序
                while (allNumber.size() % 2 == 0 && !allNumber.isEmpty()) {
                    try {
                        allNumber.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
                allNumber.add(i);
                allNumber.notify();
            }
            // 最后一次通知,防止奇数线程阻塞
            allNumber.notify();
        }
    }
}

public class Main {
    private static Scanner input = new Scanner(System.in);

    public static void main(String[] args) throws InterruptedException {
        System.out.print("Enter Your Number: ");
        int number = input.nextInt();

        List<Integer> sharedList = new ArrayList<>();

        Odd oddThread = new Odd(number, sharedList);
        Even evenThread = new Even(number, sharedList);

        Thread thread = new Thread(oddThread);
        Thread thread1 = new Thread(evenThread);

        thread.start();
        thread1.start();

        // 等待两个线程执行完毕再打印
        thread.join();
        thread1.join();

        System.out.println("List: " + sharedList);
    }
}

关键修复说明

  • 主线程等待线程完成:通过join()方法让主线程等待工作线程执行完毕,确保列表数据完整后再输出。
  • 基于列表大小的顺序控制:通过判断列表长度的奇偶性,强制偶数、奇数线程交替添加元素,保证数字按0,1,2,3...的顺序排列。
  • 循环等待避免虚假唤醒:使用while循环判断等待条件,防止线程被虚假唤醒后错误执行添加操作。
  • 收尾通知:偶数线程循环结束后额外调用一次notify(),确保奇数线程不会因最后一次等待而永久阻塞。

内容的提问来源于stack exchange,提问作者xaso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:55:19