I want to setup a FutureTask
for a expensive path finding task. So I created this Callable
class.
public class GetPath implements Callable<List<Coordinate>> {
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 (resultPath.getCount() > 0)
{
for (int i = 1; i < resultPath.getCount(); i++)
{
path.add(new Coordinate(resultPath.get(i).origin(), true));
}
}
return path;
}
}
When I execute this in a example I have seen in the constructor it still "waits" until the task is finished. While this works I am still experiencing frame drops as if I would just do it without threading.
executor = Executors.newFixedThreadPool(1);
task = new FutureTask(new GetPath(creature.getLocation(), coordinate));
//TestMap.executor.execute(task);
executor.execute(task);
try {
path = (List<Coordinate>)task.get();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception");
e.printStackTrace();
} catch (ExecutionException e) {
System.out.println("Execution Exception"); // <---
e.printStackTrace();
}
executor.shutdown();
//Works but is basically the same as just looking up a path in the main thread.
I am aware that it's pretty silly to have a thread pool of one but I'm new to this. Anyway, I tried using the same ExecutorService
a larger pool for each of the objects but without success.
Since this method is still holding the program until finished I tried watching the FutureTask
in the game loop. And when done I populate the path list and continue with the code.
if (task.isDone())
{
try {
path = (List<Coordinate>)task.get();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception");
e.printStackTrace();
} catch (ExecutionException e) {
System.out.println("Execution Exception");
e.printStackTrace();
}
executor.shutdown();
//TestMap.executor.shutdown();
}
else
{
return false;
}
//Continue with code and work with path which should now contain elements
But this gives a NullPointerException
I am unable to trace. I have checked all variables in my own code and nothing seems to be null. Perhaps I am misinterpreting task.isDone. Or perhaps I should leave the task to the executor to handle and use the executor to determine if the task is done but I am not sure how.
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:188)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.perform(GoTo.java:55)
//...
I am just looking to run some expensive code on another thread without interrupting my main game loop. I don't care how long it takes until it finds a path that is why I rather put it in a separate thread then trying to implement a much better pathfind algorithm like hierarchical A*. I am currently using gdx.ai.pfa.*
for my pathfinding.
Upon opening the current program there are 100 units waiting for a path. Each game loop 1 unit gets a path request. I'm not sure if this has any influence on what I am doing here.
>`, then you don't need to cast the raw return type.
– Andy Turner Dec 04 '15 at 13:33