这一篇将初步介绍NDK开发中多线程方面相关操作,具体步骤如下:
多线程采用 POSIX 的pthread方式实现.
<1> : 新建一个Android工程 androidpthreadjnidemo.然后在工程目录新建jni文件夹,在src下新建一个org的package,然后再这个package包下新建一个pthreadClass.java,pthreadClass的类的实现如下:
看来virtual box的剪贴板老是有问题.切换到host这边来.
<2> : 在jni目录下新建onload.h,onload.cpp,pthreadClass.cpp,其中这个pthreadClass.cpp和pthreadClass.java文件没有文件上的牵连关系,也可以命名为sb.cpp,这里只需要注意,如果是按照c++的方式实现程序代码,
那么JNIEnv* env这个用,比如:
C代码: (*env)->FindClass("org/pthreadClass"); 而C++代码: env->FindClass("org/pthreadClass"); 具体原因可以自行查找,大致思想是jni已经做了C和C++的区分,所以要注意他们的书写方式.
我这里是使用C++的,所以全部采用下面的那种书写方式.
<3> : onload.cpp,onload.h是通用的,可以在以后工程中统一都添加进来.
onload.cpp:
#include "onload.h" #include#include #include #include #include <string.h> #define TAG "jni_thread" #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)) extern int register_android_pthread_jni_demo(JNIEnv* env); JavaVM* mEnv; JavaVM* getJNIVM(){ JavaVM* env=NULL; if(mEnv->GetEnv((void**)&env,JNI_VERSION_1_4)){ return NULL; } return env; } int jniRegisterNativeMethods(JNIEnv* env,const char* classname,const JNINativeMethod* gMethods,int numMethods){ jclass classz; classz=env->FindClass(classname); if(classz==NULL){ return JNI_ERR; } if(env->RegisterNatives(classz,gMethods,numMethods)<0){ return JNI_ERR; } return JNI_OK; } int jniThrowExeption(JNIEnv *env,const char* classname){ jclass classz; classz=env->FindClass(classname); if(classz==NULL){ return JNI_ERR; } return JNI_OK; } jint JNI_OnLoad(JavaVM *vm, void *reserved){ JNIEnv* env=NULL; jint result=JNI_ERR; mEnv=vm; if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)!=JNI_OK){ return result; } if(register_android_pthread_jni_demo(env)!=JNI_OK){ goto end; //will not continue register others native methods //goto end at once } return JNI_VERSION_1_4; end: return result; }
onload.h:
#include#ifndef _ON_LOAD_HEADER_H__ #define _ON_LOAD_HEADER_H__ JavaVM* getJNIVM(); int jniRegisterNativeMethods(JNIEnv* env,const char* classname,const JNINativeMethod* gMethods,int numMethods); int jniThrowExeption(JNIEnv *env,const char* classname); jint JNI_OnLoad(JavaVM *vm, void *reserved); #endif
pthreadClass.cpp:
#include#include #include #include "onload.h" #define TAG "jni_thread" #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)) #define NUMT 5 #define JAVA_CLASS_PATH "org/pthreadClass" namespace android{ void native_init(){ LOGI("native init ."); } void* fun_in_thread(void* arg){ LOGI("enter in fun_in_thread !"); } void main_pThread(){ LOGI("MAIN THREAD"); pthread_t pt[NUMT]; int i; for(i=0;i ){ pthread_create(&pt[i],NULL,&fun_in_thread,(void*)i); } } } using namespace android; JNINativeMethod mNativeMethods[]={ { "nativeinit","()V",(void*)native_init }, { "mainthread","()V",(void*)main_pThread } }; int register_android_pthread_jni_demo(JNIEnv* env){ return jniRegisterNativeMethods(env,JAVA_CLASS_PATH,mNativeMethods,sizeof(mNativeMethods)/sizeof(mNativeMethods[0])); }
要实现多线程,必须要包含
pthread_create(&pt[i],NULL,&fun_in_thread,(void*)i);
参数说明:
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数
可以参考:https://publib.boulder.ibm.com/iseries/v5r1/ic2924/index.htm?info/apis/users_14.htm
上面的程序实现了连续创建5个线程.
Android.mk文件:
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := threadlib LOCAL_SRC_FILES := onload.cpp pthreadClass.cpp LOCAL_SHARED_LIBRARY := libnativehelper liblog #下面一句cflags可以不需要 LOCAL_CFLAGS := -llog -lpthread #添加log的 LOCAL_LDLIBS :=-llog include $(BUILD_SHARED_LIBRARY)
Android java代码中调用:
显示结果如下:
工程整个文件结构: