我不確定如何轉換我撰寫的函式,以便它在 Java 中作為多個執行緒并發運行。
該函式有一個根,對于在給定連接點“分裂”的每個執行緒來說,根是不同的(這個的 if 陳述句在函式內,每個新創建的執行緒也應該能夠在未來分裂,在下一個路口)。
我希望所有執行緒在到達目標后都死掉,但是用于檢查它們是否已到達終點的“while”回圈也在函式中。
基本上,我希望該函式能夠同時運行多次,每次都有一個修改的起點,并且在拆分之前殺死“原始”執行緒。
我也不能擴展 Thread,因為我已經擴展了另一個類,所以我試圖通過實作 Runnable 來實作。
這是課程(父課程作業正常,所以我認為我不需要發布它們):
public class Multithreaded extends ParentClass implements Runnable {
@Override
public void run() {
executeThread(modelThreaded, new HashMap<>());
}
private final Set<Tile> VISITED = new HashSet<>();
private Grid modelThreaded; //to be able to update the root?
public Multithreaded() {
super();
}
@Override
protected int runPathfinder(Grid model, List<Tile> path) {
HashMap<Tile, Integer> tileData = new HashMap<>();
this.modelThreaded = model;
this.executeThread(model, tileData);
int cost = tileData.get(model.getTarget()) - 1;
this.statistics.setPathFound(true, cost);
this.painter.drawPath(path, model);
return cost;
}
private void executeThread(Grid model, HashMap<Tile, Integer> tileData) {
// Keeps track of visited tiles
VISITED.add(model.getRoot());
//start at the root
Tile currentTile = model.getRoot();
List<Tile> posNeighbors = model.getTileNeighbors(currentTile);
List<Tile> validNeighbors = new ArrayList<>();
int DEFAULT_DISTANCE = 1;
tileData.put(model.getRoot(), DEFAULT_DISTANCE);
int iteration = 0;
while (!isVisited(model.getTarget())) {
iteration ;
posNeighbors.clear();
validNeighbors.clear();
posNeighbors = model.getTileNeighbors(currentTile);
validNeighbors = getForward(posNeighbors);
//debugging
System.out.println("Valid Neighbors for currentTile ("
currentTile.getX() ", " currentTile.getY() "): ");
for (Tile validNeighbor : validNeighbors) {
System.out.println(validNeighbor.getX() ", " validNeighbor.getY());
}
// tries to split along junctions into multithreads
// tries to kill mouse if there's a dead end
if (validNeighbors.size() > 0) {
for (Tile validNeighbor : validNeighbors) {
currentTile = validNeighbor;
// want to create a new thread for each validNeighbor here, but with
// a small change: the root changes to the current validNeighbor
model.setRoot(validNeighbor);
Runnable runnable = new Multithreaded();
Thread thread = new Thread(runnable);
thread.start();
}
}
//attempt to kill/stop current thread if there are no more options left for that thread
else {
break;
}
VISITED.add(currentTile);
tileData.put(currentTile, DEFAULT_DISTANCE iteration);
}
private List<Tile> getForward(List<Tile> posNeighbors) {
List<Tile> validNeighbors = new ArrayList<>();
for (Tile posNeighbor : posNeighbors) {
if (posNeighbor != null && !posNeighbor.isWall()
&& !isVisited(posNeighbor)) {
validNeighbors.add(posNeighbor);
}
}
return validNeighbors;
}
private boolean isVisited(Tile posNeighbor) {
for (Tile visitedTile : VISITED) {
if (visitedTile == posNeighbor) {
return true;
}
}
return false;
}
}
如您所見,我希望執行緒繼續運行,除非:
- 其中之一遇到目標(model.getTarget())或
- 它達到了有 0 個 validNeighbors 的點。
當一個執行緒有 1 個 validNeighbor 時,它應該保持單一并沿著該路徑前進,直到它到達另一個交叉點或死胡同(getForward 只回傳未訪問的鄰居)
所以,當一個執行緒遇到一個結點(2個有效鄰居)時,它應該分裂成兩個并殺死原始執行緒(停止執行executeThread,這就是我在那里放一個中斷的原因),每個方向一個執行緒,然后繼續運行演算法。使用我當前的代碼,它可以正確地沿著路徑運行,但不會分成不同的執行緒,也不會在遇到死胡同時停止運行。
讓它運行的最佳方法是什么?我將 executeThread() 放在 run() 中是否正確,還是我應該將它放在其他地方?我試過只做 runnable.run() 而不是 Thread thread 和 thread.start(),但這似乎沒有幫助。我真的不知道在這里做什么,我覺得我錯過了一些明顯的東西......
編輯:runPathfinder 是父類呼叫的函式,以便所有這些代碼運行
uj5u.com熱心網友回復:
我認為以下mre (1)重現了所需的多執行緒功能。
每個節點(狀態/圖塊)由一個整數表示。
getTileNeighbors回傳 3 個隨機鄰居。
所有執行緒共享一個同步visited集合,并且在target添加到visited.
(將整個代碼復制粘貼到 Main.java 并運行)
import java.util.*;
public class Main {
public static void main(String[] args) {
new Thread(new Multithreaded(0, 20)).start();
}
}
class Multithreaded implements Runnable {
// Synchronized Set (shared between threads)
private static final Set<Integer> visited = Collections.synchronizedSet(new HashSet<Integer>());
private final int root, target;
//root and target assumed >=0
public Multithreaded(int root, int target) {
this.root = root;
this.target = target;
}
@Override
public void run() {
executeThread(root);
}
private void executeThread(int root) {
visited.add(root);
System.out.println("New thread, root=" root);
while (!isStopConditionMet()) {
List<Integer> neighbors = getTileNeighbors(root);
//todo if neighbors is empty break out of the while loop
for (Integer neighbor : neighbors) {
if(! visited.add(neighbor)) {
continue; //skip is already visited
}
Runnable runnable = new Multithreaded(neighbor, target);
Thread thread = new Thread(runnable);
thread.start();
}
}
}
//returns a list o 3 random numbers between 0-target (inclusive)
//to represent 3 random neighbors
private List<Integer> getTileNeighbors(int currentTile) {
Random rnd = new Random();
int maxValue = target 1;
return Arrays.asList(rnd.nextInt(maxValue), rnd.nextInt(maxValue), rnd.nextInt(maxValue));
}
private boolean isStopConditionMet() {
return visited.contains(target);
}
}
(1) mre 應該演示要解決的問題,而不是特定的應用程式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/366716.html
