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

标签 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

除此之外,我不在乎路径查找是否需要几秒钟,我只是不希望我的帧速率下降,因为某些路径在较大的 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)
//....

最佳答案

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

我找到了一个样本here .

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

关于java - 在单独的线程中运行我的寻路计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34079212/

相关文章:

java - 列出 arraylist 中的数据

java - Thread.sleep() 停止我的绘画?

c# - 如何使用异步 Web 请求进行多线程处理

java - Libgdx - didpose 一遍又一遍?

java - 场景 2D 与视口(viewport)坐标和游戏坐标的分离

java - Android 中的 libgdx : how to handle escape key?

java - 如何在 Android Java 中将 strVarName.equals 嵌套在 toLowerCase 周围

java - 如何在Java中迭代NodeList并仅更新子节点?

java - 如何判断 Java 日期和时区是否早于当前时间?

c# - 如何停止 C# 中的线程?