Как решить проблему с вызовами библиотеки NDK, заморозив поток пользовательского интерфейса - PullRequest
4 голосов
/ 02 ноября 2010

У меня есть библиотека C, к которой я обращаюсь через NDK.Некоторые операции занимают много времени, поэтому поток пользовательского интерфейса останавливается на них.Как я сейчас понимаю, обычной практикой является использование Runnable следующим образом:

myFixedThreadPool.execute(new Runnable() 
{
  public void run() 
  {
    NativeClass.callToNDKLibrary();
  };
});

или подобных потоков:

Thread t = new Thread() 
{
  public void run() 
  {
    NativeClass.callToNDKLibrary();
  }
};
t.start();  

, но проблема в том, что библиотека C не безопасна для потоков: она запускаетсяпотерпеть крах, когда я заверну это так.Таким образом, вопрос состоит в том, как отсоединить от потока пользовательского интерфейса, все еще заставляя вызовы NDK запускаться по одному.Может быть поможет какой-нибудь трюк с синхронизированным?Я также хочу отметить, что эта библиотека является основным базовым уровнем для моего приложения, а не просто вспомогательной функцией.Так что он вызывается почти из каждой части моего кода.И только несколько функций занимают время, наиболее быстрое, чтобы держать их в главном потоке.

Ответы [ 3 ]

3 голосов
/ 17 ноября 2010

Окончательное решение выглядит следующим образом:

  1. Определите все собственные методы JNI как синхронизированные.Это предотвратит аварийное завершение работы библиотеки C, но все равно остановит интерфейс.
  2. Определение однопоточного исполнителя:

    ExecutorService mExecutorThread = Executors.newSingleThreadExecutor ();

  3. Обернуть все трудоемкие операции в этом потоке:

    mExecutorThread.execute (new Runnable () {public void run () {NativeClass.callToNDKLibrary ();}});

Последнее, что мне нужно было сделать, - это немного изменить мой код, чтобы убедиться, что ни один из нативных методов не вызывается из onDraw ().Я сделал результаты собственных методов, кэшированных в обработчиках событий, и использовал эти кэшированные значения в onDraw ().

2 голосов
/ 02 ноября 2010

, но проблема в том, что библиотека C не является поточно-безопасной: она начинает зависать, когда я обертываю ее следующим образом.

Затем используйте один выделенный фоновый поток для всех операций надбиблиотека.Например, используйте IntentService для доступа к библиотеке, при этом действия, вызывающие startService (), отправляют команды на IntentService.

Или:

  1. Создайте LinkedBlockingQueue<Job>, для некоторого Job класса / интерфейса, который вы определяете
  2. У вас есть один монитор потоков, который ставит в очередь
  3. Отправка заданий в эту очередь для доступа к вашей библиотеке
  4. Отправить специальный "kill job "в очередь, чтобы заставить цикл loop-the-queue завершиться, вызывая прерывание фонового потока, как только вам больше не нужны очередь и поток

или потратить время набиблиотека потокобезопасна на уровне C.Создание кода на C с поддержкой многопоточности было предметом обсуждения в течение ~ 20 лет, поэтому, вероятно, есть некоторые приемы, которые вы можете использовать, которые возникли из всего этого опыта.

0 голосов
/ 02 ноября 2010

Вы можете использовать Looper для создания цикла сообщений.Затем передайте свои вызовы NDK через Handler, и каждый будет выполняться по очереди.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...