А вот на счёт volatile. Сама по себе то она просто указывает не лесть в кэш, а значение читать и записывать на прямую в память. Возможно для boolean типа это будет и в самый раз (зависит от того, может ли поток остановиться на половине считывания этого значения, но видимо один байт (если в ней один байт) он будет читать за раз). А как лучше поступить, если хочу чтобы у меня не было путаницы в доступе с другими объектами. Сейчас опишу что я хочу...
У меня есть два потока:
1. Поток Activity
2. Поток логики
(1) вызывается сам по себе при наступлении каких-то событий:
— Activity перекрыто, возрождено;
— на экране пальцем что-то сделали;
— нажали кнопку
(2) работает пока Activity активно. И его задача — это обновление состояния игры и вывод его на экран. А состояние может обновляться несколькими способами:
— с течением времени;
— в результате произошедших событий от Activity
С течением времени — это очень просто. А что касается другого способа, то тут давайте рассмотрим. Пока Activity активно, у меня вечно крутится цикл из обновления состояния и вывод его на экран. По сути это работает параллельно (особенно если в устройстве несколько ядер). Как только я тыкнул пальцем на экран, у меня код начал выполняться не потоком обновления состояния (тот что у меня был GameThread), а потоком Activity. И в результате координаты куда тыкнули мне должны попасть как-то и в поток логики. В общем тут получается что такое нажатие может чем-то навредить другому потоку, так как он постоянно читает/записывает какие-то данные, а тут ещё эти же данные другой поток захочет изменить. Ну и вполне понятно что тут нужна синхронизация.
Как я решил сделать, я последовал примеру из Win32 API — как там это работается с окнами (как окна получают сообщения и обрабатывают их). У меня есть класс InputManager, который выглядит следующим образом:
public final class InputManager
{
private LinkedBlockingQueue<TouchEvent> qTouch;
private LinkedBlockingQueue<KeyboardEvent> qKeyboards;
public InputManager()
{
qTouch=new LinkedBlockingQueue<TouchEvent>();
qKeyboards=new LinkedBlockingQueue<KeyboardEvent>();
}
public void pushTouch(MotionEvent _event)
{
try
{
qTouch.put(new TouchEvent(_event));
}
catch(InterruptedException _exception)
{
}
}
public void pushKeyboard(KeyEvent _event)
{
try
{
qKeyboards.put(new KeyboardEvent(_event));
}
catch(InterruptedException _exception)
{
}
}
public TouchEvent popTouch()
{
return qTouch.poll();
}
public KeyboardEvent popKeyboard()
{
return qKeyboards.poll();
}
}
Поток Activity вносит события, а поток обновления игры забирает их. Вообще так то всё работает. И проблему в первом посте я решил за счёт разъединения GameThread на GameThread и Game (первый каждый раз пересоздаётся). Но что касается этого сообщения, то я беспокоюсь что такой способ может быть достаточно медленным.
Как бы Вы мне посоветовали оптимизировать программу для максимального быстродействия?