2013-07-16 2 views
0

Я использую libgdx для игры, которую я пишу, где у меня есть другой поток, который должен обновить графический поток. Я получал сбои, поскольку libgdx не был потокобезопасным (намеренно), и я разрешал другому потоку напрямую изменять переменную в графическом потоке.Можно ли использовать Runnable содержащие затворы

libgdx docs предлагает что-то похожее на следующий код. Это в основном закрытие, содержащее входящую информацию, которая затем обрабатывается, когда графический поток попадает на нее.

Я изменил его, чтобы объявить runnable вне слушателя в надежде, что я смогу избежать сбора мусора, но мне приходит в голову, что я, возможно, создал условие гонки теперь, когда runnable может быть перезаписан до графическая нить, потребляющая предыдущую информацию?

До сих пор мне удалось избежать сбора мусора повсюду, и моя игра также использует привязки аудио с низкой задержкой в ​​Android, поэтому сбор мусора - это действительно мой враг.

Любые предложения?

private Runnable runnable; 
private SomeListener listener = new SomeListener() { 
    @Override 
    public void messageIn(final String source, final String s, final Object... l) { 
     runnable = new Runnable() { 
      @Override 
      public void run() { getWorkspace().messageIn(s,l); } 
     }; 
     Gdx.app.postRunnable(runnable); 
    } 

};

ответ

1

Я изменил его, чтобы объявить исполняемые за пределы слушателя в надежде, что я мог бы избежать сбора мусора, но это происходит со мной, что я, возможно, создал условие гонки, где сейчас работоспособные может быть перезаписан до к графической нити, потребляющей предыдущую информацию?

Да, это, безусловно, может случиться. Кроме того, вы не можете использовать ThreadLocal, потому что это будут разные потоки, обрабатывающие обратный вызов по сравнению с runnable.

Что вы можете сделать, это создать BlockingQueue классов Runnable. Как только метод запуска заканчивается, Runnable может поставить себя в конце BlockingQueue для повторного использования. Когда вызывался метод messageIn(...), он вызывал бы queue.poll() и только создавал новый, если в очереди не было ни одного. Это увеличило бы синхронизацию памяти, но уменьшило бы полосу пропускания GC. Это может не сильно выиграть.

Возможно, вы планируете использовать профилировщик памяти, чтобы убедиться, что именно здесь вы должны сосредоточиться на своем рефакторинге, чтобы попытаться снизить использование памяти.

+0

Мои сообщения крошечные (ключевое слово и поплавок или два), так что это может быть хорошим вариантом. Я предполагаю, что стоимость синхронизации памяти пропорциональна размеру сообщений? И .. ох .. как я могу заставить свои закрытия работать, если я не в новом Runnable? –

+0

Стоимость синхронизации, вероятно, является линейной стоимостью - не учитывается размер сообщения @DarenSchwenke. Куда к закрытию приходят? Это анонимный класс, но я не вижу никаких закрытий. – Gray

+0

с использованием s и l из messageIn в пределах runnable run call через getWorkspace(). MessageIn (s, l); Наверное, это путают. Внешнее messageIn - это метод в моем другом потоке, внутренний - метод в графическом потоке. Сделать их окончательными во внешности по существу создает замыкание при использовании в объявлении нового права Runnable ... или я ошибаюсь. (perl guy, который начал java около 6 месяцев назад) –

1

Поскольку вы разрабатываете игру, я предлагаю вам отправить все сообщения в очередь, и вы будете потреблять тогда в игровом цикле по мере необходимости.

+0

правильно, но как мне создать сообщение, не заставляя содержимое позднее собирать мусор? Помещение объявления runnable внутри messageIn выполняет то, что вы предлагаете, но вызывает сбор мусора. –

+0

Пока ссылка на нее находится в очереди, она не будет собрана. Удалите его из очереди, расходуя его, и GC может удалить ref после этого. –

+0

Я вообще пытаюсь избежать GC. Мой текущий GC с этим методом составляет 2-5 мсек каждые 30 секунд или около того, но поскольку у меня есть только 6 мс доступного времени из-за требований к низкой задержке звука, это слишком много. postRunnable() - это метод, который я имею в распоряжении для своевременного внесения изменений в графический поток, поэтому возникает вопрос, как мне настроить и снести эти Runnables без GC. Единственный раз, когда я могу позволить себе иметь какой-либо GC, - это во время смены экрана или когда пользователь останавливает аудиовход/выход.Моим упрощенным способом сделать это было объединение и повторное использование всего до тех пор. –

Смежные вопросы