当前位置: 首页 > news >正文

JNI 编程指南12—— JNI多线程

目录

  • 核心要点
  • 示例程序

JNI多线程

核心要点

JNI 环境下,进行多线程编程,有以下两点是需明确的:

  • JNIEnv 是一个线程作用域的变量,不能跨线程传递,每个线程都有自己的 JNIEnv 且彼此独立
  • 局部引用不能在本地函数中跨函数使用,不能跨线程使用,当然也不能直接缓存起来使用

示例程序

示例程序主要演示:

如何在子线程获取到属于子线程自己的 JNIEnv
上面说了局部引用不能再线程之间直接传递,所以我们只有另觅他法
Java 层:

publicvoidjavaCallback(intcount){Log.e(TAG,"onNativeCallBack : "+count);}publicnativevoidthreadTest();

Native 层:

staticintcount=0;JavaVM*gJavaVM=NULL;//全局 JavaVM 变量jobject gJavaObj=NULL;//全局 Jobject 变量jmethodID nativeCallback=NULL;//全局的方法ID//这里通过标志位来确定 两个线程的工作都完成了再执行 DeleteGlobalRef//当然也可以通过加锁实现bool main_finished=false;bool background_finished=false;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(inti=0;i<5;i++){usleep(2);//跨线程回调Java层函数env->CallVoidMethod(gJavaObj,nativeCallback,count++);}gJavaVM->DetachCurrentThread();background_finished=true;if(main_finished&&background_finished){env->DeleteGlobalRef(gJavaObj);LOGE(TAG,"全局引用在子线程销毁");}return((void*)0);}extern"C"JNIEXPORTvoidJNICALLJava_com_yuandaima_myjnidemo_MainActivity_threadTest(JNIEnv*env,jobject thiz){//创建全局引用,方便其他函数或线程使用gJavaObj=env->NewGlobalRef(thiz);jclass clazz=env->GetObjectClass(thiz);nativeCallback=env->GetMethodID(clazz,"javaCallback","(I)V");//保存全局 JavaVM,注意 JavaVM 不是 JNI 引用类型env->GetJavaVM(&gJavaVM);pthread_tid;if(pthread_create(&id,NULL,native_thread_exec,NULL)!=0){return;}for(inti=0;i<5;i++){usleep(20);//跨线程回调Java层函数env->CallVoidMethod(gJavaObj,nativeCallback,count++);}main_finished=true;if(main_finished&&background_finished&&!env->IsSameObject(gJavaObj,NULL)){env->DeleteGlobalRef(gJavaObj);LOGE(TAG,"全局引用在主线程销毁");}}

示例代码中,我们的子线程需要使用主线程中的jobject thiz,该变量是一个局部引用,不能赋值给一个全局变量然后跨线程跨函数使用,我们通过NewGlobalRef将局部引用装换为全局引用并保存在全局变量jobject gJavaObj中,在使用完成后我们需要使用DeleteGlobalRef来释放全局引用,因为多个线程执行顺序的不确定性,我们使用了标志位来确保两个线程所有的工作完成后再执行释放操作。

JNIEnv 是一个线程作用域的变量,不能跨线程传递,每个线程都有自己的 JNIEnv 且彼此独立,实际开发中,我们通过以下代码:在子线程中获取到 JNIEnv。

JavaVM*gJavaVM=NULL;//主线程获取到 JavaVMenv->GetJavaVM(&gJavaVM);//子线程通过 JavaVM 获取到自己的 JNIEnvJNIEnv*env;gJavaVM->AttachCurrentThread(&env,NULL);

JavaVM 是一个普通指针,由 JVM 来管理其内存的分配与回收,不是 JNI 引用类型,所以 我们可以把它赋值给一个全局变量,直接用,也不用考虑他的内存分配与后续问题。


http://www.jsqmd.com/news/322106/

相关文章:

  • 5 款 AI 写论文哪个好?实测后:虎贲等考 AI 凭 “真实 + 全能” 稳赢
  • UCAS国科大 2025-2026秋 计算机网络 孙毅、张瀚文老师
  • 技能筑梦皖江淮:安徽优质职业学校盘点与择校指南
  • 2026年 包装制品厂家推荐排行榜:彩盒/纸盒/瓦楞纸箱/快递/美妆/礼品/电商/电子包装材料,创新设计与环保工艺深度解析
  • 多语言支持手动验证在软件测试中的实践
  • AI写论文哪个软件最好?6款实测后,只有它能搞定毕业论文全流程
  • 9款AI写论文哪个好?实测报告:虎贲等考AI凭真实文献+硬核数据碾压同类
  • pg常用数据字典
  • 基于元模型优化的虚拟电厂主从博弈优化调度模型探索
  • AI 写论文哪个软件最好?虎贲等考 AI 凭全流程合规硬核,成毕业生终极答案
  • 从 0 到开通抖音带货橱窗,新手最快只需要 3 步
  • 2026年全国路灯厂家权威推荐榜 智能化节能化适配多场景工程指南全景解析
  • PLC网关有什么推荐?哪个品牌好用?
  • 必收藏!2026 AI应用爆发详解(小白/程序员必看,五大核心板块快速上手)
  • 安徽学技术怎么选?这份安徽职业学校指南,藏着安心答案
  • Java毕设项目推荐-基于java+springboot的模拟证券交易软件平台系统可视化大屏【附源码+文档,调试定制服务】
  • aws 常用命令
  • 2026年家具定制终极选型指南:ENF环保口径与快工期交付闭环融合的广州深圳东莞源头工厂深度测评
  • 第三方软件课题验收测试【使用Docker容器部署LoadRunner负载生成器以实现弹性压测 】
  • 互联网大厂Java求职面试实战:Spring Boot、微服务与AI技术栈综合解析
  • 2026酱香白酒厂家优选推荐:53度酱香白酒,穗百顺酱酒领衔,纯粮工艺适配各类品鉴场景
  • 上天翼云,一键开启你的AI助手“Moltbot”(原名Clawdbot)!
  • 2026年成都竹笋食品行业竹笋/手剥笋/竹笋食品/泡椒笋营销技术服务商TOP5权威评估与选型指南报告
  • 聊聊焊工焊接培训学校哪家性价比高
  • argocd 提示信息:The resources will be synced using ‘kubectl replace/create‘ command that.....
  • 微信鸿蒙版 8.0.14 查询 navigator.maxTouchPoints 为 0 导致的 bug
  • ArgoCD 中资源存在不可变字段修改的含义和举例
  • 2026年河南口碑好的保温材料公司推荐,大杨保温材料详细介绍
  • 2026年 贺卡定制厂家推荐排行榜:激光镂空/3D立体/纸雕贺卡,高级感祝福贺卡品牌精选
  • Java毕设选题推荐:基于SpringBoot+Vue的模拟证券交易软件平台的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】