【问题标题】:Java: Stuck in the while loop in the background threadJava:卡在后台线程的while循环中
【发布时间】:2016-05-31 20:23:43
【问题描述】:

我正在使用 LibGDX AsyncExecutor,并且在后台线程中调用了以下函数。 'tasksForTheMainThread' 是 Runnable 的静态数组,它在每次调用主线程中的更新函数期间执行其尚未执行的元素。 “modelBuilder”的函数“createBox”创建并返回一个“模型”类的对象。

简单解释一下,这段代码在第二个线程中执行,并发送一段代码(函数'run()')在第一个线程中使用。发送后,第二个线程被冻结,直到“run()”中的代码完成并创建模型对象(或者至少应该是这样)。

但是,只有当 while 循环(它只是等待直到在主线程中创建对象)包含日志记录位 (Gdx.app.log("TAG","2");) 时,它才能按预期工作。当它为空时,第二个线程将永远冻结,即使在创建模型对象之后也永远不会到达“点 A”。

日志记录为什么以及如何影响这一点?为什么没有它程序就不能工作?

void secondThreadFunction()
{
    Model model = null;

    ChunkManager.tasksForTheMainThread.add(new Runnable()
    {
                    @Override
                    public void run()
                    {
                            model = modelBuilder.createBox(size.x, size.y, size.z, GL20.GL_LINES,
                                    new Material(ColorAttribute.createDiffuse(Color.YELLOW)),
                                    VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal);
                    }
     });

     while (model == null)
     {
            //Gdx.app.log("TAG","2");
     }

      //point A
}

【问题讨论】:

  • 不应该modelvolatile 吗?这实际上可能是问题......与并行核心和触发同步的日志记录有关。第二个线程没有做任何事情,因此可能永远不会获得数据的更新视图,因为model 不是volatile。此外,上述代码不可编译,因为model 不是成员或final

标签: java multithreading logging libgdx


【解决方案1】:

您不能修改已捕获到内部类的局部变量。既然已经被“捕获”了,你会操作一个值的副本,它永远不会是非null,导致死循环。另请注意,您正忙于在一个紧凑的循环中等待。使用某种Future 可能会更好。

void secondThreadFunction()
{
    AtomicReference<Model> model = new AtomicReference<Model>();

    ChunkManager.tasksForTheMainThread.add(new Runnable()
    {
                    @Override
                    public void run()
                    {
                            model.set(modelBuilder.createBox(size.x, size.y, size.z, GL20.GL_LINES,
                                    new Material(ColorAttribute.createDiffuse(Color.YELLOW)),
                                    VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal));
                    }
     });

     while (model == null)
     {
            //Gdx.app.log("TAG","2");
     }

      //point A
}

【讨论】:

  • 您确定Model model 是局部变量而不是类成员吗?在后面的情况下,可能是Gdx.app.log() 有一个内存屏障(例如synchronized),可能需要它来反映另一个线程上的更改。
  • AtomicReference 会起作用,但它不会解决紧循环中的忙等待问题。
猜你喜欢
  • 1970-01-01
  • 2015-06-15
  • 2020-03-01
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
  • 2010-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多