当前位置: 首页 > news >正文

多线程猜数问题

题目:线程 A 生成随机数,另外两个线程来猜数,线程 A 可以告诉猜的结果是大还是小,两个线程都猜对后,游戏结束,编写代码完成。

一、Semaphore

多个线程可以同时操作同一信号量,由此实现线程同步。

public class Main {
    private static Semaphore s1 = new Semaphore(0);
    private static Semaphore s2 = new Semaphore(0);
    // 待判断的线程
    private static Queue<Semaphore> judgeQueue = new LinkedList<>();
    // 保存线程猜的数
    private static Map<Semaphore, Integer> guessMap = new ConcurrentHashMap<>();
    // 保存判断结果
    private static Map<Semaphore, Integer> resMap = new ConcurrentHashMap<>();
    // 保存猜数线程二分过程中的左右边界
    private static Map<Semaphore, Pair<Integer, Integer>> edgeMap = new ConcurrentHashMap<>();
    private static Set<Semaphore> set = new HashSet<>();

    public static void main(String[] args) {
        new Thread(Main::judge, "判断线程").start();
        new Thread(() -> guess(s1), "猜线程1").start();
        new Thread(() -> guess(s2), "猜线程2").start();
    }

    private static void judge() {
        System.out.println("开始猜数!");
        int num = ThreadLocalRandom.current().nextInt(100);
        System.out.printf("要猜的数是 %d\n", num);
        set.add(s1);
        set.add(s2);
        s1.release();
        s2.release();

        while (true) {
            while (!judgeQueue.isEmpty()) {
                Semaphore s = judgeQueue.poll();
                Integer guessNum = guessMap.get(s);
                if (guessNum != null) {
                    if (guessNum > num) {
                        resMap.put(s, 1);
                    } else if (guessNum < num) {
                        resMap.put(s, 2);
                    } else {
                        resMap.put(s, 0);
                    }
                    s.release();
                } else {

                }
            }
            if (set.isEmpty()) {
                System.out.println("所有线程猜数完成!\n");
                break;
            }
        }
    }

    private static void guess(Semaphore s) {
        Pair<Integer, Integer> edge = new Pair<>(0, 100);
        edgeMap.put(s, edge);
        int guess = 0;
        while (true) {
            try {
                s.acquire();
                guess = guessNum(guess, s);
                if (guess != -1) {
                    guessMap.put(s, guess);
                    judgeQueue.add(s);
                } else {
                    System.out.printf("%s 猜数成功!\n", Thread.currentThread().getName());
                    set.remove(s);
                    break;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static int guessNum(int guess, Semaphore s) {
        Pair<Integer, Integer> pair = edgeMap.get(s);
        if (resMap.containsKey(s)) {
            int res = resMap.get(s);
            // 1 表示猜大了
            if (res == 1) {
                edgeMap.put(s, new Pair<>(pair.getKey(), guess - 1));
            } else if (res == 2) {
                edgeMap.put(s, new Pair<>(guess + 1, pair.getValue()));
            } else {
                // 猜中了
                return -1;
            }
            guess = (pair.getKey() + pair.getValue()) / 2;
        } else {
            guess = ThreadLocalRandom.current().nextInt(100);
        }
        System.out.printf("%s 猜的数是:%s\n", Thread.currentThread().getName(), guess);
        return guess;
    }
}

暂时没想到更好的解法,也欢迎大家指教。

相关文章:

  • AI CUDA 工程师:Agentic CUDA 内核发现、优化和组合
  • 前后台系统
  • JavaScript单例模式
  • JS—Token与JWT
  • [测试] Google Test | 主流的 C 测试框架
  • 2024最新鸿蒙开发面试题合集(二)-HarmonyOS NEXT Release(API 12 Release)
  • 网络命名空间验证网络重叠现象
  • SpringBoot3.x 集成 shardingsphere-jdbc 实现读写分离
  • 26考研|数学分析:反常积分
  • JSON for Modern C++ 解析 JSON(五)
  • 【Git】5 个分区的切换方式及示例
  • idea报错:程序包不存在
  • 【android bluetooth 协议分析 13】【RFCOMM详解 1】【通俗易懂 什么是rfcomm】
  • 数理天地杂志数理天地杂志社数理天地编辑部2025年第6期目录
  • Java的比较器 Comparable 和 Comparator
  • 如何批量拆分Excel工作表或按行拆分Excel表格 - Excel拆分器使用方法
  • 通信协议与网络知识:从硬件到互联网的全面指南
  • 什么是 MCP(模型上下文协议)
  • 10乱码问题的解释(1)
  • GLPI 在企业 IT 资产全生命周期管理中的价值
  • 关税影响下沃尔玛想涨价,特朗普施压:自行承担,别转嫁给顾客
  • 新疆多地市民拍到不明飞行物:几秒内加速消失,气象部门回应
  • 玛丽亚·凯莉虹口连唱两夜,舞台绽放唤醒三代人青春记忆
  • 莫高义在第四届中国新闻发言人论坛开幕式上的致辞
  • 嫩黑线货物列车脱轨致1名路外人员死亡,3人被采取刑事强制措施
  • 马上评|训斥打骂女儿致死,无暴力应是“管教”底线