2016-05-31 13 views
0

Ich benutze LibGDX AsyncExecutor und die folgende Funktion wird in einem Hintergrund-Thread aufgerufen. 'tasksForTheMainThread' ist das statische Array von Runnable, das bei jedem Aufruf der Update-Funktion im Haupt-Thread seine noch nicht ausgeführten Elemente ausführt. Die Funktion 'createBox' von 'modelBuilder' erstellt und gibt ein Objekt der Klasse 'Model' zurück.Java: Fest in der While-Schleife im Hintergrund Thread

Kurz erklärt, dieser Code wird im zweiten Thread ausgeführt und sendet einen Code (Funktion 'run()'), der im ersten Thread verwendet werden soll. Nach dem Senden ist der zweite Thread bis zu dem Moment eingefroren, in dem der Code in "run()" abgeschlossen ist und das Model-Objekt erstellt wird (oder zumindest so sein soll).

Es funktioniert jedoch wie erwartet nur, wenn die While-Schleife (die nur wartet, bis das Objekt im Hauptthread erstellt wird) das Protokollierungsbit (Gdx.app.log("TAG","2");) enthält. Wenn es leer ist, friert der zweite Thread für immer ein und erreicht selbst nach der Erstellung des Model-Objekts nie den Punkt A.

Warum und wie kann die Protokollierung das beeinflussen? Und warum funktioniert das Programm nicht ohne?

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 
} 
+0

Sollte 'Modell' nicht' volatile' sein? Das könnte tatsächlich das Problem sein ... etwas mit parallelen Kernen zu tun und das Logging löst eine Synchronisierung aus. Der zweite Thread tut nichts und erhält vielleicht nie eine aktualisierte Ansicht der Daten, da "Modell" nicht "flüchtig" ist. Außerdem ist der obige Code nicht kompilierbar, da "Modell" kein Mitglied oder "final" ist. – Tenfour04

Antwort

0

Sie können eine lokale Variable, die in einer inneren Klasse erfasst wurde, nicht ändern. Da es "eingefangen" wurde, werden Sie eine Kopie des Wertes bearbeiten und es wird niemals null sein, was die Endlosschleife verursacht. Beachten Sie auch, dass Sie beschäftigt sind und in einer engen Schleife warten. Es könnte besser sein, ein Future irgendeiner Art zu verwenden.

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 
} 
+0

Warum funktioniert es dann mit der Anmeldung in der Schleife? –

+0

Sind Sie sicher, dass 'Model model' eine lokale Variable und kein Klassenmitglied ist? In einem späteren Fall könnte es sein, dass "Gdx.app.log()" eine Speicherbarriere (z. B. eine "synchronisierte") aufweist, die erforderlich sein könnte, um die Änderung auf dem anderen Thread widerzuspiegeln. –

+0

Sie haben Recht. Es ist ein Feld der Klasse. –

Verwandte Themen