# Running a method in another thread and get result.

This topic is 955 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I want to have my pathfinding logic in a separate thread. I have little experience with threads and have tried just running a method from a new Runnable() or Thread I am currently trying it with FutureTask but without success.

This is the Callable where call() to run on a separate thread.

public class GetPath implements Callable {

private Coordinate start;
private Coordinate end;

public GetPath(Coordinate start, Coordinate end) {
this.start = start;
this.end = end;
}

@Override
public List<Coordinate> call() throws Exception {

IndexedNodeImplementation location = TestMap.mapgraph.getNodeByCoord(start.x, start.y);
IndexedNodeImplementation destination = TestMap.mapgraph.getNodeByCoord(end.x, end.y);
GraphPathImplementation resultPath = new GraphPathImplementation();

List<Coordinate> path = new ArrayList<Coordinate>();

TestMap.pathFinder.searchNodePath(location, destination, new HeuristicImplementation(), resultPath);

if (path == null)
{
System.out.println("path");
}

if (resultPath.getCount() > 0)
{
for (int i = 1; i < resultPath.getCount(); i++)
{
}
}
return path;
}
} 

So when I give a task to a unit that requires movement this needs to be called and while calculating it should continue with the game. When it is finished it should populate a list with coordinates (the path) and work with that.

private List<Coordinate> path = new ArrayList<Coordinate>();
ExecutorService executor;

public GoTo(final Creature creature, final Coordinate coordinate) {

//getPath(creature, coordinate); //Previous way of getting the path without threads
}

In my update method I check if the task is done and if it's done I try to populate path. Otherwise I return since there is nothing to do without a path.

  @Override
public boolean perform(final Creature creature) {
{
try {
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
}
else return false;

//... Do something with path
}

But this yields ExecutionExceptions.

java.util.concurrent.ExecutionException: java.lang.NullPointerExceptionat java.util.concurrent.FutureTask.report(FutureTask.java:122)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.perform(GoTo.java:49)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.Hauling.perform(Hauling.java:40)
//...

If I would just use the try/catch to populate in the constructor it just waits for the task to be done and results in the same behaviour as without threading (framedrop).

Most of the pathfinding tasks are well within 10ms but sometimes it goes over 100ms and when multiple units require a path things slow down. I am currently stress testing this and want the game to keep running smooth while the pathfinding can take it's time to finish. I don't even care if it takes a minute to find certain paths.

Edited by menyo

##### Share on other sites

The problem was lying in the following line:

TestMap.pathFinder.searchNodePath(location, destination, new HeuristicImplementation(), resultPath);

I was using this pathfinder for each thread and since this changes state I was getting errors. So I created a new pathfinder in the Runnable. Eventually when the map is dynamic I will probably need to do the same for the graph or make a deep copy of it's current state so when it the map alters during the pathfinding it will still find a (incorrect) path once the unit realizes the path is incorrect it requests a new path or cancels it's job.

##### Share on other sites

Usually one doesn't allocate a FutureTask oneself, instead you let the ExecutorService do so under the hood. I'd generally recommend that you switch to calling executor.submit(new GetPath(creature.getLocation(), coordinate)), and deal directly with Future, rather than FutureTask (which is mostly an implementation detail).

As to tracing down your error, we need the next section of the stack trace from your logs. Just after the error you posted, there should be a line that says "Caused by: java.lang.NullPointerException..." followed by a stack trace of whatever failed within your background task.

Edit: ninja'd by the OP :)

Edited by swiftcoder

1. 1
Rutin
24
2. 2
3. 3
JoeJ
18
4. 4
5. 5

• 38
• 23
• 13
• 13
• 17
• ### Forum Statistics

• Total Topics
631706
• Total Posts
3001833
×