工作流如下圖所示,要求每一個任務只執行一次,不重複執行,要求任務的所有前置任務必須完成才能往後執行,例如任務7必須在任務13,2,3三個任務完成之後才能執行,而任務13,2,3屬於獨立的任務,可以併發執行
根據多線程要求得出5個路線數據
每個線程可以獨立執行,所有線程相同的任務不能重複執行,當前任務必須在前置任務完成之後才能執行,
路線:[1, 2, 7, 10, 12]
路線:[1, 13, 7, 10, 12]
路線:[1, 3, 7, 10, 12]
路線:[1, 4, 8, 10, 12]
路線:[1, 4, 9, 11, 12]
路線:[1, 5, 6, 9, 11, 12]
路線不能出現迴環,出現即死循環,需要提前排除
實現代碼如下(JDK1.8)
數據結構類NetWork
import java.util.*; /** * 圖解網絡數據結構 */ public class NetWork { //記錄兩份網絡節點,使用空間換時間,提升反向查詢效率 //網絡初始化,x_k,y_k private Map<String, Map<String, String>> xMapMap; //網絡初始化,y_k,x_k private Map<String, Map<String, String>> yMapMap; //迴環路徑 private List<String> loopbackList;//迴環地址 //節點深度路徑 private List<List<String>> deepPathList;//深度路徑 private Map<String, String> jobMapStatus;//map任務狀態 enum TYPE {X,Y} public NetWork() { xMapMap = new HashMap();//X點集 yMapMap = new HashMap();//Y點集 loopbackList = new LinkedList<>();//迴環地址 deepPathList = new LinkedList<>();//深度路徑 } /** * 初始化任務 */ public void initJob() { jobMapStatus = new HashMap<>(); Set<String> allPoint = getAllPoint(); allPoint.forEach(job -> jobMapStatus.put(job, "0"));//0,1 0表示未執行,1表示執行 } /** * 獲取任務的轉狀態 * * @param job * @return */ public String getJobMapStatus(String job) { String status = jobMapStatus.get(job); return status; } /** * 更新任務的狀態 * * @param job 任務名稱 * @param status 任務狀態 */ public void setJobMapStatus(String job, String status) { jobMapStatus.put(job, status); } public List<String> getLoopbackList() { return loopbackList; } public List<List<String>> getDeepPathList() { return deepPathList; } /** * 網絡添加節點 * * @param xPoint x位 * @param yPoint y位 * @param distance 位移 */ public void addPoint(String xPoint, String yPoint, String distance) { if (!xMapMap.containsKey(xPoint)) {//記錄x的索引 xMapMap.put(xPoint, new HashMap<>()); } xMapMap.get(xPoint).put(yPoint, distance); if (!yMapMap.containsKey(yPoint)) {//記錄y的索引 yMapMap.put(yPoint, new HashMap<>()); } yMapMap.get(yPoint).put(xPoint, distance); } /** * 根據座標獲取某點 * * @param xPoint * @param yPoint * @return */ public String getPoint(String xPoint, String yPoint) { Map<String, String> linePoints = xMapMap.get(xPoint); String point = linePoints.get(yPoint); return point; } public String getPoint(String point1, String point2, TYPE type) { if (type == TYPE.X) { Map<String, String> linePoints = xMapMap.get(point1); String point = linePoints.get(point2); return point; } else { Map<String, String> linePoints = yMapMap.get(point1); String point = linePoints.get(point2); return point; } } /** * 獲取X軸的一列數據 * * @param xPoint * @return */ public List<Map<String, String>> getLinePoint(String xPoint) { List<Map<String, String>> linePointList = new ArrayList<Map<String, String>>(); Map<String, String> linePoints = xMapMap.get(xPoint); if (linePoints != null) { for (Map.Entry<String, String> pointUnit : linePoints.entrySet()) { Map<String, String> pointMap = new HashMap<String, String>(); pointMap.put("X", xPoint); pointMap.put("Y", pointUnit.getKey()); pointMap.put("D", pointUnit.getValue()); linePointList.add(pointMap); } } return linePointList; } /** * 根據類型獲取某軸的一列數據 * * @param point 索引點 * @param type 類型 * @return */ public List<Map<String, String>> getLinePoint(String point, TYPE type) { List<Map<String, String>> linePointList = new ArrayList<Map<String, String>>(); if (type == TYPE.X) { Map<String, String> linePoints = xMapMap.get(point); if (linePoints != null) { for (Map.Entry<String, String> pointUnit : linePoints.entrySet()) { Map<String, String> pointMap = new HashMap<String, String>(); pointMap.put("X", point); pointMap.put("Y", pointUnit.getKey()); pointMap.put("D", pointUnit.getValue()); linePointList.add(pointMap); } } } else { Map<String, String> linePoints = yMapMap.get(point); if (linePoints != null) { for (Map.Entry<String, String> pointUnit : linePoints.entrySet()) { Map<String, String> pointMap = new HashMap<String, String>(); pointMap.put("X", pointUnit.getKey()); pointMap.put("Y", point); pointMap.put("D", pointUnit.getValue()); linePointList.add(pointMap); } } } return linePointList; } /** * @param netWork 網絡節點 * @param startPoint 起始節點 * @param pathList 當前任務的路徑 */ public void recursive(NetWork netWork, String startPoint, ArrayList<String> pathList) { if (pathList.contains(startPoint)) {netWork.getLoopbackList().add(pathList.toString() + "->" + startPoint);return;} pathList.add(startPoint); List<Map<String, String>> linePoint = netWork.getLinePoint(startPoint, NetWork.TYPE.X); if (linePoint.size() == 0) { ArrayList<String> descList = new ArrayList<>(pathList.size()); pathList.forEach(path -> descList.add(path)); netWork.getDeepPathList().add(descList); } for (Map<String, String> map : linePoint) {recursive(netWork, map.get("Y"), pathList);} pathList.remove(startPoint); } /** * 獲取所有的點,合併key * * @return */ public Set<String> getAllPoint() { Set<String> allSet1 = xMapMap.keySet(); Set<String> allSet2 = yMapMap.keySet(); Set<String> allSet = new HashSet<>(); allSet.addAll(allSet1); allSet.addAll(allSet2); return allSet; } /** * 顯示路徑 */ public void show() { int placeholder = 3; String placeholderSrting = ""; for (int i = 0; i < placeholder; i++) {placeholderSrting = placeholderSrting + "-";} Set<String> allSet = getAllPoint();//獲取所有的點,用於遍歷 System.out.print(String.format("%-" + placeholder + "s", "")); System.out.print(" "); for (String x : allSet) { System.out.print(String.format("%-" + placeholder + "s", x)); } System.out.println(); System.out.print(String.format("%-" + placeholder + "s", "X\\Y")); System.out.print(" "); for (String ignored : allSet) {System.out.print(placeholderSrting);} System.out.println(); for (String x : allSet) { System.out.print(String.format("%-" + placeholder + "s|", x)); for (String y : allSet) { Map<String, String> linePoints = xMapMap.get(x); String point = "0"; if (linePoints != null && linePoints.get(y) != null) { point = linePoints.get(y); } System.out.print(String.format("%-" + placeholder + "s", point)); } System.out.println(); } } }
測試類TestMain
import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * 網絡計算 */ public class TestMain { public static ConcurrentMap<String, List<String>> println = new ConcurrentHashMap<>(); public static List<String> strings = new ArrayList<>(); public static void main(String[] args) throws InterruptedException { NetWork netWork = new NetWork(); netWork.addPoint("1", "2", "1"); netWork.addPoint("1", "3", "1"); netWork.addPoint("1", "4", "1"); netWork.addPoint("1", "5", "1"); netWork.addPoint("1", "13", "1"); netWork.addPoint("2", "7", "1"); netWork.addPoint("3", "7", "1"); netWork.addPoint("13", "7", "1"); netWork.addPoint("4", "8", "1"); netWork.addPoint("4", "9", "1"); netWork.addPoint("5", "6", "1"); netWork.addPoint("6", "9", "1"); netWork.addPoint("7", "10", "1"); netWork.addPoint("8", "10", "1"); netWork.addPoint("9", "11", "1"); netWork.addPoint("10", "12", "1"); netWork.addPoint("11", "12", "1"); netWork.initJob();//初始化所有節點任務 // netWork.addPoint("6", "1", "1");netWork.addPoint("4", "6", "1");//迴環的兩條數據 netWork.show(); //獲取起點,如圖起點爲1 String startPoint = "1"; netWork.recursive(netWork, startPoint, new ArrayList<>()); //遞歸計算所有節點的路徑 if (netWork.getLoopbackList().size() != 0) { System.out.println("出現迴環地址,迴環地址的路徑爲:" + netWork.getLoopbackList()); return; } //開始計算任務 for (List<String> pathJobList : netWork.getDeepPathList()) { new Thread(() -> { System.out.println("路線:" + pathJobList); for (int i = 0; i < pathJobList.size(); i++) { String job = pathJobList.get(i); List<String> linePoint = new ArrayList<>();//獲取任務前置條件 netWork.getLinePoint(job, NetWork.TYPE.Y).forEach(jobLine -> linePoint.add(jobLine.get("X"))); // System.out.println("任務" + job + "的前置條件:" + linePoint); execJob(job, linePoint, netWork);//執行任務 } }).start(); } Thread.sleep(1000); for (Map.Entry<String, List<String>> entry : println.entrySet()) { System.out.println(entry); } System.out.println("執行順序:" + strings); } /** * 執行任務 * * @param job */ private static void execJob(String job, List<String> linePoint, NetWork netWork) { List<String> tmp = new ArrayList<>(); while (true) { for (String precondition : linePoint) { String jobMapStatus; synchronized (String.class) {jobMapStatus = netWork.getJobMapStatus(precondition);} if (!"1".equals(jobMapStatus)) {tmp.add(precondition);}//未執行 } if (tmp.size() == 0) {break;} linePoint.clear(); tmp.forEach(jobTmp -> linePoint.add(jobTmp)); tmp.clear(); // try {Thread.sleep(100);} catch (InterruptedException e) { e.printStackTrace();} } String jobMapStatus; Boolean status = false;//是否需要執行任務 synchronized (String.class) { jobMapStatus = netWork.getJobMapStatus(job); if ("1".equals(jobMapStatus)) {return;}//任務已經完成 if ("0".equals(jobMapStatus)) {netWork.setJobMapStatus(job, "-1");status = true;}//立即執行 } if (status) { synchronized (String.class) { if (!println.containsKey(Thread.currentThread().getName())) { println.put(Thread.currentThread().getName(), new ArrayList<>()); } println.get(Thread.currentThread().getName()).add(job);strings.add(job); netWork.setJobMapStatus(job, "1"); } } } }
測試結果如下
實現原理是使用矩陣,X軸表示起始點,Y軸表示結束點,起始點與結束點對應的值爲1 即表示起始點與結束點之間是一條通線,如果值爲0 即表示這兩點之間不通
根據矩陣原理開發
起始點對應的一行中所有值爲1的結束點爲起始點可到達的結束點
結束點對應的一列中所有值爲1的起始點是結束點所表示任務的前置任務
所以數據結構NetWork類中已經封裝好了通過x,y座標獲取一個值和通過x或者通過y獲取一行或者一列數據的方法