ExecutorService和Future阻塞了主线程

问题描述

我正在用Java开发游戏,我实现了一个多线程系统来执行地形生成,这是一项重复性的任务(〜10-20个任务,每个任务在一帧中花费约10-20ms)。目标是:

  • 划分任务花费的时间,因为我不希望我的播放器在地形产生时停滞。

  • 不要等待地形生成。例如,如果我在移动并且前方的地形仍在生成,我不希望主线程等待生成地形,我希望游戏继续运行直到将来完成并且信息已完成检索以渲染地形。

达到第一个目标时,生成地形的速度相对较快,但是只要生成地形,主线程就会被阻塞,从而在生成时冻结。

这是我的代码:

//method called each frame
private void checkForFutures(List<Future<SomeClass>> terrainsInCreation) {
        System.out.println("NEW CHECK"); 
        try
        {
            List<Future<SomeClass>> futuresToRemove = new ArrayList<Future<SomeClass>>();
            for(Future<SomeClass> future:terrainsInCreation) {
                if(future.isDone()) {
                    float time = DisplayManager.getCurrentTime();
                    try {
                        SomeClass t = future.get();
                        // Some instructions (EDIT:)
                        Key key = new Key(t.terrain.getChunkX(),t.terrain.getChunkZ());
                        t.terrain.generateTerrain(loader,t.vertices,t.indices,t.colors,t.normals); // Guilty line !

                        terrains.put(key,t.terrain);
                        terrainsToRender.add(t.terrain);
                        futuresToRemove.add(future);
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                        Thread.sleep(1000000);
                    }
                    System.out.println("future done,took: " + (DisplayManager.getCurrentTime()-time)); 
// The first future is always taking ~ 100-200ms,which is the time it takes to generate all the terrains
// roughly divided by 4,which is the numbers of core I have
                }
            }
            terrainsInCreation.removeAll(futuresToRemove);
        }
        catch (InterruptedException ie)
        {
            System.err.println("BIG PROBLEM ON TERRAIN MANAGER");          
        }
    }

//method called when I have terrains to generate
    private void generate(List<Callable<SomeClass>> terrainsToCreate) {

        for(int i = 0; i < terrainsToCreate.size();i++) {
            terrainsInCreation.add(executor.submit(terrainsToCreate.get(i)));
        } 
    }

以下是印刷品的输出:

NEW CHECK
NEW CHECK
NEW CHECK
NEW CHECK
future done,took: 165.0
future done,took: 1.0
future done,took: 0.0
future done,took: 2.0
future done,took: 0.0
NEW CHECK
NEW CHECK
NEW CHECK
NEW CHECK

如您所见,我正在使用future.isDone()方法,但是如果它找到一个已完成的未来,则在调用future.get()时它仍然会阻塞,证明是我最后正在做的打印这样会给第一个未来留出大量时间,然后每个未来会留出1ms的时间来检索正常行为的信息。

我的问题是如何从字面上并行执行任务,并在完成时检索结果,而又不阻塞主线程? (不应该等待未完成的期货)

修改

我将脚本隔离在一个最小的可复制项目中,问题消失了,罪魁祸首是//Some instructions之一,因此首先我将这些行添加到上面的代码中,然后我将继续调查并更新帖子。

我终于隔离了冻结整个过程的一行:

int vaoID = GL30.glGenVertexArrays();

因此,基本上,在获得未来之后,我打电话给terrain.generate,它根据顶点,法线,颜色等信息创建一个模型。要创建模型,我首先创建一个vao,创建此vao的第一步是此行,并且在此框架中首次创建该vao时,它会冻结直到所有其他期货完成为止!

我不得不说我肯定迷路了,我不知道要做什么。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...