需求:玩家會隨機加入遊戲,當第一個玩家加入匹配後最多等待時間T,每局遊戲固定人數N git代碼庫:https://gitee.com/ichiva/game_matching.gitjava
匹配接口
package com.company; import java.util.Collection; import java.util.Set; /** * 通用匹配 * * @param <T> */ public interface Match<T> { /** * 添加匹配 * @param ele */ void add(T ele); /** * 匹配成功 * @param list */ void success(Collection<T> list); /** * 匹配失敗,未達到固定匹配人數 * @param list */ void fail(Collection<T> list); }
超時匹配實現
package com.company; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.*; /** * 超時匹配 * @param <T> */ public abstract class TimeoutMatch<T> extends Thread implements Match<T> { /** * 匹配超時時間 */ private final long timeout; private final int capacity; private final ExecutorService executorService; private final LinkedBlockingDeque<T> deque = new LinkedBlockingDeque<>(); public TimeoutMatch(int capacity, long timeout){ this(capacity,timeout,Executors.newSingleThreadExecutor()); } public TimeoutMatch(int capacity, long timeout,ExecutorService executorService){ this.capacity = capacity; this.timeout = timeout; this.executorService = executorService; start(); } @Override public void add(T ele){ deque.push(ele); } @Override public void run() { while (!Thread.currentThread().isInterrupted()){ try { T start = deque.take(); System.out.println("匹配開始"); Future<Set<T>> submit = executorService.submit(new Task(start)); try { Set<T> list = submit.get(timeout, TimeUnit.SECONDS); success(list); }catch (TimeoutException e) { submit.cancel(true); }catch (Exception e){ e.printStackTrace(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } private class Task implements Callable<Set<T>>{ private final T start; public Task(T start){ this.start = start; } @Override public Set<T> call() { Set<T> list = new LinkedHashSet<>(capacity); list.add(start); System.out.println("放入臨時匹配隊列" + start); try { while (list.size() != capacity){ T ele = deque.take(); list.add(ele); System.out.println("放入臨時匹配隊列" + ele); } }catch (InterruptedException e) { fail(list); } return list; } } }
測試用例
package com.company.test; import com.company.TimeoutMatch; import java.util.Collection; import java.util.UUID; public class TimeoutMatchTests { public static void main(String[] args) throws InterruptedException { TestTimeoutMatch match = new TestTimeoutMatch(3,3); while (true){ int num = (int) (Math.random() * 3); System.out.printf("加入【%d】人\r\n", num); for (int i = 0; i < num; i++) { match.add(UUID.randomUUID().toString()); } Thread.sleep(1500); } } static class TestTimeoutMatch extends TimeoutMatch<String> { public TestTimeoutMatch(int capacity, long timeout) { super(capacity, timeout); } @Override public void success(Collection<String> list) { System.out.println("匹配成功"); for (String item : list) { System.out.println("\t" + item); } } @Override public void fail(Collection<String> list) { System.err.println("匹配失敗"); for (String item : list) { System.err.println("\t" + item); } } } }
測試結果
加入【1】人 匹配開始 放入臨時匹配隊列865cf9b3-fe43-4b88-89de-cc7c79fb5f84 加入【0】人 加入【1】人 放入臨時匹配隊列117b966c-d7b0-492d-aff2-cb31bffa207e 匹配失敗 865cf9b3-fe43-4b88-89de-cc7c79fb5f84 117b966c-d7b0-492d-aff2-cb31bffa207e 加入【1】人 匹配開始 放入臨時匹配隊列7b944eaa-7e44-4895-8bec-0b3e011fb562 加入【2】人 放入臨時匹配隊列ac89eec4-5324-490b-a420-a454f59b2220 放入臨時匹配隊列44feee0c-eafa-4cdc-9223-6a43f5c24782 匹配成功 7b944eaa-7e44-4895-8bec-0b3e011fb562 ac89eec4-5324-490b-a420-a454f59b2220 44feee0c-eafa-4cdc-9223-6a43f5c24782 加入【2】人 匹配開始 放入臨時匹配隊列a5544b6d-4d22-4eb6-92ed-4bef946f6fa6 放入臨時匹配隊列69203001-0440-48e5-8247-f8775bc32cad 加入【1】人 放入臨時匹配隊列55a6dde9-8e82-42da-a3d5-50331ba11664 匹配成功 a5544b6d-4d22-4eb6-92ed-4bef946f6fa6 69203001-0440-48e5-8247-f8775bc32cad 55a6dde9-8e82-42da-a3d5-50331ba11664 加入【2】人 匹配開始 放入臨時匹配隊列11a6ae84-ba43-495a-af45-87f753424281 放入臨時匹配隊列37af5d04-e12e-4cf8-8685-738047984051