文章目录
I . JNI 线程创建
- I . JNI 线程创建
- II . 线程执行函数
- III . 线程方法获取 Java 对象
- IV . 线程方法获取 JNIEnv
- V . JNI 线程 完整代码示例
1. 线程创建方法函数原型 :
int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void*), void *arg)`;
2. pthread_create 方法的 4 个参数 ;
- 参数 1 ( pthread_t *tidp ) : 线程标识符指针 , 该指针指向线程标识符 ;
- 参数 2 ( const pthread_attr_t *attr ) : 线程属性指针 ;
- 参数 3 ( (void*)(*start_rtn)(void*) ) : 线程运行函数指针 , start_rtn 是一个函数指针 , 其参数和返回值类型是 void* 类型 ;
- 参数 4 ( void *arg ) : 参数 3 中的线程运行函数的参数 ;
3. 返回值说明 :
- 线程创建成功 , 返回 0 ;
- 线程创建失败 , 返回 错误代码 ;
4. 关于函数指针参数的说明 : C++ 中函数指针类型是 void *(PTW32_CDECL *start) (void *)
- 函数的参数类型是 void* 指针 ;
- 函数的返回值类型 void* 指针 ;
5. 函数多参数方案 : 如果线程执行的函数有多个参数 , 可以使用结构体 , 类进行封装 ;
6. 线程属性 : 创建线程时 , 给线程指定属性 pthread_attr_t 是结构体类型 ;
7. 代码示例 :
/*
线程创建方法函数原型 :
int pthread_create(
pthread_t *tidp,
const pthread_attr_t *attr,
(void*)(*start_rtn)(void*),
void *arg);
该方法需要提供四个参数 ;
参数 1 ( pthread_t *tidp ) :线程标识符指针 , 该指针指向线程标识符 ;
参数 2 ( const pthread_attr_t *attr ) : 线程属性指针 ;
参数 3 ( (void*)(*start_rtn)(void*) ) : 线程运行函数指针 , start_rtn 是一个函数指针 ,
其参数和返回值类型是 void* 类型
参数 4 ( void *arg ) : 参数 3 中的线程运行函数的参数 ;
返回值 :
线程创建成功 , 返回 0 ;
线程创建失败 , 返回 错误代码 ;
关于函数指针参数 : C++ 中函数指针类型是 void *(PTW32_CDECL *start) (void *) ,
函数的参数类型是 void* 指针
函数的返回值类型 void* 指针
函数多参数方案 : 如果线程执行的函数有多个参数 , 可以使用结构体 , 类进行封装
线程属性 : 创建线程时 , 给线程指定属性 pthread_attr_t 是结构体类型
*/
//函数指针 函数名 和 &函数名 都可以作为函数指针
pthread_create( &pid , 0 , threadRun, 0 );
II . 线程执行函数
1. 线程执行函数的要求 : C++ 中规定线程执行函数的函数指针类型是 void *(PTW32_CDECL *start) (void *)
;
2. 函数作用 : 将该函数的指针作为线程创建方法 pthread_create 的第三个参数 ;
3. 参数处理 : 在线程创建时 , 传入参数 , 将该参数转为 char* 字符串指针类型 , 将其打印出来 ;
4. 代码示例 :
/*
定义线程中要执行的方法
将该函数的指针作为线程创建方法 pthread_create 的第三个参数
C++ 中规定线程执行函数的函数指针类型是 void *(PTW32_CDECL *start) (void *)
*/
void* pthread_function(void* args) {
//延迟 100 ms 执行
//_sleep(100);
//指针类型转换 : 将 void* 转为 char*
// 使用 static_cast 类型转换标识符
char* hello = static_cast(args);
//打印参数
cout GetMethodID(clazz, "logThread", "()V");
//调用 logThread 方法
env->CallVoidMethod(obj, logThreadID);
//释放相关的局部变量
env->DeleteLocalRef(clazz);
//将线程从 Java 虚拟机中剥离
_vm->DetachCurrentThread();
//注意这里一定要返回 0 , 否则执行到结尾会崩溃
return 0;
}
void threadDemoC(JNIEnv *env, jobject instance){
__android_log_print(ANDROID_LOG_INFO, "JNI_TAG", "threadDemoC");
//保存全局变量 , 先将局部变量转为全局变量 , 然后再赋值给全局的 obj 变量
// 使用域作用符访问全局的 ::obj 变量
::obj = env->NewGlobalRef(instance);
//代表一个线程的句柄
pthread_t pid;
//创建线程并执行
pthread_create( &pid , 0 , threadRun, 0 );
}
//下面的代码是动态注册内容
static const JNINativeMethod methods[] = {
{"threadDemoJava", "()V", (void *)threadDemoC}
};
static const char* className = "kim/hsl/thread/MainActivity";
int JNI_OnLoad(JavaVM *vm , void* reserved){
// 1 . 记录 Java 虚拟机指针
_vm = vm;
// 2 . 动态注册方法
//获取 JNIEnv 指针
JNIEnv *env = nullptr;
int registerResult = vm->GetEnv( (void **) &env, JNI_VERSION_1_6 );
if(registerResult != JNI_OK){
return -1;
}
//进行动态注册
jclass jclazz = env->FindClass(className);
env->RegisterNatives(jclazz, methods, sizeof(methods) / sizeof(JNINativeMethod));
return JNI_VERSION_1_6;
}
3 . 执行结果 :
2020-02-08 23:47:58.253 25293-25293/? I/JNI_TAG: threadDemoC
2020-02-08 23:47:58.253 25293-25316/? I/JNI_TAG: threadRun
2020-02-08 23:47:58.253 25293-25316/? I/JNI_TAG: Thread[Thread-2,10,main]