如何在JNI中使用线程
1个回答
2016-08-15 · 百度知道合伙人官方认证企业
育知同创教育
1【专注:Python+人工智能|Java大数据|HTML5培训】 2【免费提供名师直播课堂、公开课及视频教程】 3【地址:北京市昌平区三旗百汇物美大卖场2层,微信公众号:yuzhitc】
向TA提问
关注
展开全部
JNIEnv* g_env;
jobject g_thiz;
JavaVM *g_jvm;
void* thread_get_str(void * argv) {
(g_jvm)->AttachCurrentThread(&g_env, NULL);
LOGE("log in another thread!!!!!!!!!!");
jclass clazz = (g_env)->GetObjectClass(g_thiz);
jfieldID fid = (g_env)->GetFieldID(clazz, "mInstanceName", "Ljava/lang/String;");
jstring jstr = (jstring)(g_env)->GetObjectField(g_thiz, fid);
LOGE("this message is from other thread of c++ %s", (g_env)->GetStringUTFChars(jstr, NULL));
(g_jvm)->DetachCurrentThread();
}
void threadTest(JNIEnv* env, jobject thiz) {
if (g_thiz) {
(g_env)->DeleteGlobalRef(g_thiz);
}
g_thiz = (env)->NewGlobalRef(thiz);
g_env = env;
pthread_t thread;
pthread_create(&thread, NULL, thread_get_str, NULL);
}
看到了么关键是(g_jvm)->AttachCurrentThread(&g_env, NULL); 和(g_jvm)->DetachCurrentThread(); 函数,是把当前的线程绑定到jvm上,我们通过全局变量实现了参数的传递,当然了,其实我们也可以调用AndroidRuntime::getRuntime来获得vm但是比较麻烦,因为有些头文件的配置比较麻烦。至此,我们成功的在c++层使用了线程。
尽管现在中国的工程师还是比较急功近利,总是期望知道是什么,而很少问为什么,但是我觉得一个优秀的工程师应该知道为什么。
首先为什么我们不调用那两个函数就无法使用线程。我的功力有限,简单的看了下,我们JNI函数中的,evn其实是当前线程的环境参数,使用当我们创建新的线程就无法使用了,当我们调用AttachCurrentThread就是为当前线程创建一些环境参数。
1,AttachCurrentThread 调用 attachThread
2, JavaVMAttachArgs argsCopy;
if (args == NULL) {
/* allow the v1.1 calling convention */
argsCopy.version = JNI_VERSION_1_2;
argsCopy.name = NULL;
argsCopy.group = (jobject) dvmGetMainThreadGroup();
} else {
assert(args->version >= JNI_VERSION_1_2);
argsCopy.version = args->version;
argsCopy.name = args->name;
if (args->group != NULL) {
argsCopy.group = (jobject) dvmDecodeIndirectRef(NULL, args->group);
} else {
argsCopy.group = (jobject) dvmGetMainThreadGroup();
}
}
bool result = dvmAttachCurrentThread(&argsCopy, isDaemon);
这里我们copy了当期的环境参数到新的线程中。
然后接下来就创建线程,然后让线程跑起来。
jobject g_thiz;
JavaVM *g_jvm;
void* thread_get_str(void * argv) {
(g_jvm)->AttachCurrentThread(&g_env, NULL);
LOGE("log in another thread!!!!!!!!!!");
jclass clazz = (g_env)->GetObjectClass(g_thiz);
jfieldID fid = (g_env)->GetFieldID(clazz, "mInstanceName", "Ljava/lang/String;");
jstring jstr = (jstring)(g_env)->GetObjectField(g_thiz, fid);
LOGE("this message is from other thread of c++ %s", (g_env)->GetStringUTFChars(jstr, NULL));
(g_jvm)->DetachCurrentThread();
}
void threadTest(JNIEnv* env, jobject thiz) {
if (g_thiz) {
(g_env)->DeleteGlobalRef(g_thiz);
}
g_thiz = (env)->NewGlobalRef(thiz);
g_env = env;
pthread_t thread;
pthread_create(&thread, NULL, thread_get_str, NULL);
}
看到了么关键是(g_jvm)->AttachCurrentThread(&g_env, NULL); 和(g_jvm)->DetachCurrentThread(); 函数,是把当前的线程绑定到jvm上,我们通过全局变量实现了参数的传递,当然了,其实我们也可以调用AndroidRuntime::getRuntime来获得vm但是比较麻烦,因为有些头文件的配置比较麻烦。至此,我们成功的在c++层使用了线程。
尽管现在中国的工程师还是比较急功近利,总是期望知道是什么,而很少问为什么,但是我觉得一个优秀的工程师应该知道为什么。
首先为什么我们不调用那两个函数就无法使用线程。我的功力有限,简单的看了下,我们JNI函数中的,evn其实是当前线程的环境参数,使用当我们创建新的线程就无法使用了,当我们调用AttachCurrentThread就是为当前线程创建一些环境参数。
1,AttachCurrentThread 调用 attachThread
2, JavaVMAttachArgs argsCopy;
if (args == NULL) {
/* allow the v1.1 calling convention */
argsCopy.version = JNI_VERSION_1_2;
argsCopy.name = NULL;
argsCopy.group = (jobject) dvmGetMainThreadGroup();
} else {
assert(args->version >= JNI_VERSION_1_2);
argsCopy.version = args->version;
argsCopy.name = args->name;
if (args->group != NULL) {
argsCopy.group = (jobject) dvmDecodeIndirectRef(NULL, args->group);
} else {
argsCopy.group = (jobject) dvmGetMainThreadGroup();
}
}
bool result = dvmAttachCurrentThread(&argsCopy, isDaemon);
这里我们copy了当期的环境参数到新的线程中。
然后接下来就创建线程,然后让线程跑起来。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询