題目:線程 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;}
}
暫時沒想到更好的解法,也歡迎大家指教。