核心内容摘要
Face Analysis WebUI进阶使用:如何通过API集成到你的应用中
目录核心要点示例程序JNI多线程核心要点JNI 环境下进行多线程编程有以下两点是需明确的JNIEnv 是一个线程作用域的变量不能跨线程传递每个线程都有自己的 JNIEnv 且彼此独立局部引用不能在本地函数中跨函数使用不能跨线程使用当然也不能直接缓存起来使用示例程序示例程序主要演示如何在子线程获取到属于子线程自己的 JNIEnv上面说了局部引用不能再线程之间直接传递所以我们只有另觅他法Java 层publicvoidjavaCallback(intcount){Log.e(TAG,onNativeCallBack : count);}publicnativevoidthreadTest();Native 层staticintcount0;JavaVM*gJavaVMNULL;//全局 JavaVM 变量jobject gJavaObjNULL;//全局 Jobject 变量jmethodID nativeCallbackNULL;//全局的方法ID//这里通过标志位来确定 两个线程的工作都完成了再执行 DeleteGlobalRef//当然也可以通过加锁实现bool main_finishedfalse;bool background_finishedfalse;staticvoid*native_thread_exec(void*arg){LOGE(TAG,nativeThreadExec);LOGE(TAG,The pthread id : %d\n,pthread_self());JNIEnv*env;//从全局的JavaVM中获取到环境变量gJavaVM-AttachCurrentThread(env,NULL);//线程循环for(inti0;i5;i){usleep(
;//跨线程回调Java层函数env-CallVoidMethod(gJavaObj,nativeCallback,count);}gJavaVM-DetachCurrentThread();background_finishedtrue;if(main_finishedbackground_finished){env-DeleteGlobalRef(gJavaObj);LOGE(TAG,全局引用在子线程销毁);}return((void*)
;}externCJNIEXPORTvoidJNICALLJava_com_yuandaima_myjnidemo_MainActivity_threadTest(JNIEnv*env,jobject thiz){//创建全局引用方便其他函数或线程使用gJavaObjenv-NewGlobalRef(thiz);jclass clazzenv-GetObjectClass(thiz);nativeCallbackenv-GetMethodID(clazz,javaCallback,(I)V);//保存全局 JavaVM注意 JavaVM 不是 JNI 引用类型env-GetJavaVM(gJavaVM);pthread_tid;if(pthread_create(id,NULL,native_thread_exec,NULL)!
{return;}for(inti0;i5;i){usleep(
;//跨线程回调Java层函数env-CallVoidMethod(gJavaObj,nativeCallback,count);}main_finishedtrue;if(main_finishedbackground_finished!env-IsSameObject(gJavaObj,NULL)){env-DeleteGlobalRef(gJavaObj);LOGE(TAG,全局引用在主线程销毁);}}示例代码中我们的子线程需要使用主线程中的jobject thiz该变量是一个局部引用不能赋值给一个全局变量然后跨线程跨函数使用我们通过NewGlobalRef将局部引用装换为全局引用并保存在全局变量jobject gJavaObj中在使用完成后我们需要使用DeleteGlobalRef来释放全局引用因为多个线程执行顺序的不确定性我们使用了标志位来确保两个线程所有的工作完成后再执行释放操作。
JNIEnv 是一个线程作用域的变量不能跨线程传递每个线程都有自己的 JNIEnv 且彼此独立实际开发中我们通过以下代码在子线程中获取到 JNIEnv。
JavaVM*gJavaVMNULL;//主线程获取到 JavaVMenv-GetJavaVM(gJavaVM);//子线程通过 JavaVM 获取到自己的 JNIEnvJNIEnv*env;gJavaVM-AttachCurrentThread(env,NULL);JavaVM 是一个普通指针由 JVM 来管理其内存的分配与回收不是 JNI 引用类型所以 我们可以把它赋值给一个全局变量直接用也不用考虑他的内存分配与后续问题。