题目:线程 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;}
}
暂时没想到更好的解法,也欢迎大家指教。