我对线程非常新,我想让我的探路者在它上面运行单独的线程。
对于少量单位(当游戏打开时所有人都请求路径)它会工作一段时间,但后来我得到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
除此之外,我不在乎路径查找需要几秒钟我不想让我的帧速率下降,因为有些路径在较大的地图上需要> 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
,似乎可以在上面的示例中使用。但是它只是等待任务/线程完成所以我得到的结果与没有线程,framedrop相同。
我希望这可以在我的游戏循环中运行:
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)
//....
答案 0 :(得分:1)
如果您只想使用线程来计算某些结果并且不想管理它的生命周期,请尝试在并发包中使用FutureTask
和ExecutorService
。
我找到了一个示例here。
如果你想真正理解这些问题,我强烈建议你阅读“实践中的Java并发”。