我对线程非常陌生,我想让我的探路者在单独的线程上运行。
对于少量单位(游戏打开时所有单位都请求路径),它可以工作一段时间,但随后我会收到 NullPointerException
和 IllegalThreadStateException
。
...
GoTo: New path for nr: 10. [9ms]
Item: item picked up by: nr: 2
Item: item picked up by: nr: 0
GoTo: New path for nr: 1. [10ms]
GoTo: New path for nr: 2. [2ms]
GoTo: New path for nr: 0. [3ms]
Item: item dropped by: nr: 11
Item: item dropped by: nr: 2
Item: item dropped by: nr: 12
Item: item dropped by: nr: 20
Item: item dropped by: nr: 0
Exception in thread "Thread-38" java.lang.NullPointerException
at com.badlogic.gdx.utils.BinaryHeap.down(BinaryHeap.java:124)
at com.badlogic.gdx.utils.BinaryHeap.remove(BinaryHeap.java:72)
at com.badlogic.gdx.utils.BinaryHeap.pop(BinaryHeap.java:60)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:113)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:93)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:50)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.getPath(GoTo.java:93)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.access$000(GoTo.java:18)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo$1.run(GoTo.java:47)
GoTo: New path for nr: 2. [27ms]
Exception in thread "LWJGL Application" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:684)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.perform(GoTo.java:62)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.Hauling.perform(Hauling.java:40)
at com.buckriderstudio.buriedkingdoms.Creatures.Creature.update(Creature.java:52)
at com.buckriderstudio.buriedkingdoms.Creatures.CreatureHandler.update(CreatureHandler.java:50)
at com.buckriderstudio.buriedkingdoms.World.TestMap.update(TestMap.java:114)
at com.buckriderstudio.buriedkingdoms.BuriedKingdoms.render(BuriedKingdoms.java:49)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:215)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)
GoTo: New path for nr: 12. [1ms]
GoTo: New path for nr: 20. [4ms]
GoTo: New path for nr: 0. [27ms]
我首先尝试在需要路径的构造函数中启动线程。在开始线程之前我常常在那里查找它。现在我将其移至更新循环中调用的方法,但得到了相同的结果。
public GoTo(final Creature creature, final Coordinate coordinate) {
test = new Thread()
{
@Override
public void run() {
super.run();
getPath(creature, coordinate);
}
};
//getPath(creature, coordinate); //Old way without threads
}
以下内容每帧都会被调用,但它不应该多次调用线程,因为它会检查它是否还活着,并且当它完成时它应该有一个路径。
@Override
public boolean perform(final Creature creature) {
if (path == null)
{
if (!test.isAlive())
test.start();
return false;
}
我从构造函数中的线程代码开始:
new Thread(new Runnable() {
@Override
public void run() {
getPath(creature, coordinate);
}
}).start();
如果我在 1000x1000 的人身上放置 100 个单位,事情就会立即开始出错。
"C:\Program ...
Exception in thread "Thread-3" java.lang.NullPointerException
at com.badlogic.gdx.utils.BinaryHeap.down(BinaryHeap.java:115)
at com.badlogic.gdx.utils.BinaryHeap.remove(BinaryHeap.java:72)
at com.badlogic.gdx.utils.BinaryHeap.pop(BinaryHeap.java:60)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:113)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:93)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:50)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.getPath(GoTo.java:82)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.access$000(GoTo.java:18)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo$1.run(GoTo.java:43)
at java.lang.Thread.run(Thread.java:724)
Exception in thread "Thread-1" java.lang.NullPointerException
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:114)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:93)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:50)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.getPath(GoTo.java:82)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.access$000(GoTo.java:18)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo$1.run(GoTo.java:43)
at java.lang.Thread.run(Thread.java:724)
GoTo: New path for nr: 2. [2ms]
Exception in thread "Thread-5" java.lang.NullPointerException
Exception in thread "Thread-6" java.lang.NullPointerException
at com.badlogic.gdx.utils.BinaryHeap.down(BinaryHeap.java:124)
at com.badlogic.gdx.utils.BinaryHeap.remove(BinaryHeap.java:72)
at com.badlogic.gdx.utils.BinaryHeap.pop(BinaryHeap.java:60)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:113)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:93)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:50)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.getPath(GoTo.java:82)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.access$000(GoTo.java:18)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo$1.run(GoTo.java:43)
at java.lang.Thread.run(Thread.java:724)
Exception in thread "Thread-8" Exception in thread "Thread-7" java.lang.NullPointerException
at com.badlogic.gdx.utils.BinaryHeap.down(BinaryHeap.java:134)
at com.badlogic.gdx.utils.BinaryHeap.remove(BinaryHeap.java:72)
at com.badlogic.gdx.utils.BinaryHeap.pop(BinaryHeap.java:60)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:113)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:93)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:50)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.getPath(GoTo.java:82)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.access$000(GoTo.java:18)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo$1.run(GoTo.java:43)
at java.lang.Thread.run(Thread.java:724)
java.lang.NullPointerException
at com.badlogic.gdx.utils.BinaryHeap.down(BinaryHeap.java:134)
at com.badlogic.gdx.utils.BinaryHeap.remove(BinaryHeap.java:72)
at com.badlogic.gdx.utils.BinaryHeap.pop(BinaryHeap.java:60)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.search(IndexedAStarPathFinder.java:113)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:93)
at com.badlogic.gdx.ai.pfa.indexed.IndexedAStarPathFinder.searchNodePath(IndexedAStarPathFinder.java:50)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.getPath(GoTo.java:82)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo.access$000(GoTo.java:18)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.GoTo$1.run(GoTo.java:43)
at java.lang.Thread.run(Thread.java:724)
GoTo: New path for nr: 7. [2ms]
Exception in thread "Thread-10" java.lang.NullPointerException
GoTo: New path for nr: 9. [0ms]
Exception in thread "Thread-12" java.lang.NullPointerException
Exception in thread "Thread-13" java.lang.NullPointerException
除此之外,我不在乎路径查找是否需要几秒钟,我只是不希望我的帧速率下降,因为某些路径在较大的 map 上需要>100毫秒。
-编辑-
我已经在未来的任务中尝试过它:
public GoTo(最终的生物,最终的坐标坐标){
ExecutorService executor = Executors.newFixedThreadPool(2);
task = new FutureTask(new GetPath(creature.getLocation(), coordinate));
executor.execute(task);
try {
path = (List<Coordinate>)task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//getPath(creature, coordinate);
}
GetPath
实现了 Callable
并且似乎在上面的示例中工作。但它只是等待任务/线程完成,所以我得到与没有线程相同的结果,帧丢失。
我希望这能在我的游戏循环中发挥作用:
if (task.isDone())
{
try {
path = (List<Coordinate>)task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
else return false;
但它会产生NullPointerExceptions
。
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:56)
at com.buckriderstudio.buriedkingdoms.Creatures.Jobs.Hauling.perform(Hauling.java:40)
//....
最佳答案
如果您只想使用线程来计算某些结果并且不想管理其生命周期,请尝试并发使用 FutureTask
和 ExecutorService
包裹。
我找到了一个样本here .
如果你想真正理解这些问题,我强烈建议你阅读《Java并发实践》。
关于java - 在单独的线程中运行我的寻路计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34079212/