C++/Java 绑定:应该在哪一侧实现多线程?

C++/Java bindings : In which side should multi-threading be implemented?

我正在我的库中实现一个名为 HttpDataStream 的 C++ class。我必须执行 JNI 绑定才能在 Android 下使用我的库,而 Objective-C 绑定用于 iOS.

我需要在 Java 和 Objective-C 中创建一个专用的 HttpDataStream class,但我想知道这些 classes 是否真的会阻止整个应用程序,直到下载完成。

例如,让我们在 "Android side" 上从 HttpDataStream class 调用一个 read 方法:

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 方法将下载文件和 return 下载的字节数。我目前在想,即使我在 "Android side" 上使用 Threads 和 Runnables,C++ 库实际上也会阻塞,直到下载完成。

所以我问自己以下问题:

如果这是一个较长的下载操作,那么在 Android 下,建议从线程内部(可能是前台)服务中进行。这样,一旦用户隐藏它,系统就不会杀死您的应用程序。在这种情况下,最好在 java 侧创建线程。

在我处理的应用程序中,我有很多在其自己的本机线程中执行的本机代码。此代码通过调用 java class 上的方法进行 HTTP 通信 - 它包装了各种 android HTTPClient 方法。这些大多是少量数据。

所以:

Should multi-threading be implemented both on the C++ and Java side ?

对于少量数据,我会在 C++ 代码中进行线程处理并调用 java class 来包装 HTTPClient 或 URL。您可以使用此 pthreads,它应该在 android 和 ios 上工作,只需稍作改动。

对于大量数据,至少在 android 下 - 在服务中使用 java 线程。这实际上使得在 c++ 中编写像读取这样的操作变得困难。

我不确定流式数据,据我所知是你的情况,如果你立即需要数据 - 那么本机线程应该是最好的。

答案取决于您对多线程的期望:

a) 一侧的流水线相关操作

如果您的 read() 在 Java 端执行多个依赖操作,例如读取、解释或预处理数据,并最终呈现它,您可以考虑在 java 边。

但是无论你在那一边做什么,你对流 class' read() 的单次调用只有在 java 上的所有多线程操作时才会 return边完成。所以是的,在这种情况下,C++ 代码被卡住了,等待 return。

b) 做一些不相关的事情

所以如果你想让你的C++代码在读取数据时做一些其他的事情,但与获取的数据无关,你应该考虑在C++端做多线程(不要忘记附加JNI环境到新线程!)。

c) 双方流水线相关动作

但是如果你需要在C++端Java处理部分获取的数据(例如开始显示数据),那么你可以选择以下两种方法之一:

  • C++ 中的多线程,前提是您有办法同时访问正在 java 中读取的数据(e.g.reading 小块,或 java 函数可以访问正在填充缓冲区)
  • java 中的多线程每次部分数据准备就绪时调用本机 C++ 函数作为回调:在这种情况下,JNI 将处理 运行 不同线程中的每个回调 C++ 函数对应于Java线程。

java 或 C++

中的观察者

这取决于您的选择和与先前选择相关的限制。不了解更多,很难给你 objective 和有用的建议。