3 потока, работающие с высокой частотой, используют одни и те же переменные

Я разрабатываю приложение для Android, которое с высокой частотой получает данные от ble notify, печатает данные на экране и отправляет данные на другие периферийные устройства.

Это моя ситуация:

  1. Обратный вызов onCharacteristicChanged получает массив байтов с именем «value» с частотой 10 Гц и распаковывает данные в некоторые переменные типа float и int.

  2. обработчик, связанный с handlerThread, запускает Runnable каждые 30 Гц. Этот исполняемый модуль использует переменные, распакованные из value, сохраняет новые данные в некоторых переменных и отправляет широковещательное сообщение в UX.

  3. другой поток каждые 10 Гц использует данные, сохраненные на шаге 1, а шаг 2 выполняет некоторые математические операции с этими переменными и записывает данные о характеристике.

На шаге выше я сохраняю и использую переменные float, double и int.

Я боюсь обрабатывать параллелизм и думаю решить проблемы с параллелизмом, используя один и тот же поток обработчиков на шагах 2 и 3. Но когда приходит другое уведомление, я думаю, что есть проблема с условием гонки: /

другой вопрос: oncharacteristicchanged в каком потоке выполняется?

дополнительная информация о моей проблеме: в oncharacteristicchanged поступает новый массив байтов (на частоте 10 Гц), я распаковываю данные в переменные, в другом потоке B (на частоте 30 Гц) использую эти данные, делаю некоторые вычисления: и сохранить результат в некоторых других переменных; поток C использует результат потока B, он выполняет другие вычисления и записывает характеристику на частоте 10 Гц.

oncharacteristicchanged -> Тема B -> Тема C

Но я не могу остановиться на изменении характеристики, потому что я не знаю, в каком потоке это выполняется.

Ты


person aeroxr1    schedule 11.09.2015    source источник
comment
Вы можете начать с Параллелизм Java на практике (jcip.net).   -  person fadden    schedule 12.09.2015
comment
Да, я должен купить эту книгу, но прежде я должен решить проблему выше :(   -  person aeroxr1    schedule 12.09.2015


Ответы (1)


Я не понимаю Android, но я делаю Java. Я постараюсь помочь вам даже не зная Android, так что поехали!

"На шаге выше я сохраняю и использую переменные типа float, double и int."

Прежде всего, я бы начал использовать потокобезопасные переменные, такие как: AtomicInteger, или объявить их как volatile.

Для всех ваших методов, к которым будет обращаться многопоточность, я бы сказал, чтобы они были потокобезопасными. Я не знаю, есть ли в Android класс Lock или ключевое слово synchronized, но я бы начал оттуда.

Пример:

Lock lock = new ReentrantLock();
try  {
    lock.lock();
    doYourWork();
} finally{
    lock.unlock();
}

Вот с чего начать... Надеюсь, я немного помог вам, даже не зная Android, и извините, если я сказал что-то не так.

person Lucas    schedule 11.09.2015
comment
Благодаря ответу. Первоначально я думал использовать объект блокировки, но что произойдет, если новые данные поступят в oncharacteristicchanged, а тем временем другой поток удерживает блокировку? - person aeroxr1; 12.09.2015
comment
Затем поток, получающий доступ к измененной характеристике, должен ждать, пока поток, удерживающий блокировку, не разблокирует объект. Пример: MyClass mc = new MyClass(); mc.wait(); //hold the lock of the object doStuff(); mc.notify(); //release the lock to anyother thread take it! Кроме того, используйте его внутри потокобезопасного метода и обязательно всегда разблокируйте свои объекты, чтобы избежать зависания потоков, и будьте осторожны с взаимоблокировками (советую вам прочитать об этом)! - person Lucas; 13.09.2015
comment
Спасибо. Но я думаю, что oncharacteristicchanged работает в потоке U, поэтому я не должен его останавливать.. однако мне интересно, действительно ли oncharacteristicchanged работает в потоке пользовательского интерфейса или нет.. ммм.. - person aeroxr1; 13.09.2015
comment
Ps: когда вы используете метод wait(), убедитесь, что он находится внутри синхронизированного блока, иначе он вызовет исключение java.lang.IllegalMonitorStateException. Кроме того, я предлагаю установить время ожидания блокировки объекта с помощью wait(int), чтобы вы могли избежать зависания Threading. - person Lucas; 13.09.2015
comment
Конечно, вы можете остановить это. Вызов метода join() в классе Thread заставляет все остальные потоки ожидать того, кто вызывает join(). Пример: Thread t1 = new Thread(your runnable here); t1.join(); // Hey other threads, wait for me to end my job, then you can continue from here. - person Lucas; 13.09.2015
comment
Извините, я сделал ошибку в сообщении выше. Я бы сказал, что я не знаю, работает ли oncharacteristicchanged в потоке пользовательского интерфейса (поток в Android, который обрабатывает графику), я не должен останавливать этот поток. Если я не могу остановиться на изменении характеристик, что я могу сделать? - person aeroxr1; 13.09.2015