问题描述
我正在用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 (将#修改为@)