在单独的线程中运行我的寻路计算

时间:2015-12-04 01:06:47

标签: java multithreading libgdx

我对线程非常新,我想让我的探路者在它上面运行单独的线程。

对于少量单位(当游戏打开时所有人都请求路径)它会工作一段时间,但后来我得到NullPointerExceptionIllegalThreadStateException

...
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)
//....

1 个答案:

答案 0 :(得分:1)

如果您只想使用线程来计算某些结果并且不想管理它的生命周期,请尝试在并发包中使用FutureTaskExecutorService

我找到了一个示例here

如果你想真正理解这些问题,我强烈建议你阅读“实践中的Java并发”。