Привязки C++/Java: В какую сторону должна быть реализована многопоточность?
Я реализую класс C++ под названием HttpDataStream
в моей библиотеке. Я должен сделать привязки JNI, чтобы использовать мою библиотеку под Android с привязками Objective C для iOS.
Мне нужно создать выделенный HttpDataStream
класс на Java и Objective-C, но мне интересно, будут ли эти классы фактически блокировать все приложение до завершения загрузки.
Например, давайте назовем read
метод из HttpDataStream
класс на "стороне Android":
std::streamsize DataStreamJava::read(double value) {
jmethodID m = jni->GetMethodID(j_dataStream_class_,
"read", "(D)J");
jni->CallLongMethod(j_dataStream_global_, m);
return 0;
}
Скажем read
Метод загрузит файл и вернет количество загруженных байтов. В настоящее время я думаю, что даже если я использую Threads и Runnables на стороне Android, библиотека C++ будет фактически блокироваться, пока загрузка не будет завершена.
Поэтому я задаю себе следующие вопросы:
- Должна ли многопоточность быть реализована как на стороне C++, так и на стороне Java?
- Должен ли я реализовать DataStreamObserver в C++, который будет вызываться после завершения загрузки?
2 ответа
Ответ зависит от того, что вы ожидаете от многопоточности:
а) конвейеризация связанных действий на одной стороне
Если твой read()
на стороне Java выполняет несколько зависимых действий, таких как чтение, интерпретация или предварительная обработка данных и, в конечном итоге, их рендеринг, вы можете рассмотреть возможность выполнения многопоточности на стороне java.
Но как бы вы ни делали это на той стороне, ваш единственный вызов потоковому классу read()
вернется только тогда, когда все многопоточные действия на стороне Java будут завершены. Так что да, в этом случае код C++ застрял, ожидая возврата.
б) делать что-то не связанное
Поэтому, если вы хотите, чтобы ваш код C++ делал что-то еще, пока данные читаются, но не связаны с полученными данными, вам следует рассмотреть возможность выполнения многопоточности на стороне C++ (не забудьте присоединить среду JNI к новым потокам!).
c) конвейеризация связанных действий с обеих сторон
Но если вам нужно обработать некоторую часть собранных данных с помощью Java на стороне C++ (например, начать отображение данных), то вы можете выбрать один из следующих двух подходов:
- многопоточность в C++, при условии, что у вас есть способ одновременного доступа к данным, которые читаются в Java (например, чтение небольших кусков или функция Java, дающая доступ к заполняемым буферам)
- многопоточность в вызове java для собственных функций C++ в качестве функции обратного вызова каждый раз, когда некоторые частичные данные готовы: в этом случае JNI позаботится о запуске каждой вызываемой функции C++ в отдельном потоке, соответствующем потоку Java.
Наблюдатель в Java или в C++
Это зависит от вашего выбора и ограничений, связанных с предыдущим выбором. Не зная больше, трудно дать вам объективный и полезный совет.
Если это более длительная операция загрузки, то в Android рекомендуется делать это из потока внутри (возможно, переднего плана) сервиса. Таким образом, система не убьет ваше приложение, когда пользователь его скрывает. В этом scenerio лучше создать нить на стороне Java.
В приложении, над которым я работаю, у меня много собственного кода, который выполняется в собственных собственных потоках. Этот код выполняет HTTP-коммуникацию, вызывая методы в классе java, который включает в себя различные методы AndroidCroid HTTP. Это в основном небольшие объемы данных.
Так:
Должна ли многопоточность быть реализована как на стороне C++, так и на стороне Java?
для небольших объемов данных я бы делал потоки в коде C++ и вызывал бы класс java, который оборачивает HTTPClient или URL. Вы можете использовать для этого pthreads, который должен работать на Android и IOS с небольшими изменениями.
Для больших объемов данных, по крайней мере, под Android - используйте поток Java в сервисе. Это фактически затрудняет кодирование таких операций, как чтение на С ++.
Я не уверен насчет потоковых данных, что, как я понимаю, в вашем случае, если вам нужны данные немедленно, тогда лучше использовать нативные потоки.