Java里的线程和操作系统的线程是一一对应的,为了方便理解Thread 类的底层实现,我们可以自己来仿造一个MyThread, 同样接受一个Runable接口,调用start实现run方法。
这是要实现的类
1 2 3 4 5 6 7
| public class MyThread { Runnable mRunnable; public MyThread(Runnable runnable) { mRunnable = runnable; } native public void start(); }
|
那么我们先去实现native方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #define TAG "native-lib" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
JavaVM *jvm = 0; jclass RunnableClass = NULL; extern "C" JNIEXPORT void JNICALL Java_com_test_MyThread_start(JNIEnv *env, jobject thiz) { LOGD("java invoke start()---------------start"); jclass MyThreadClass = env->FindClass("com/test/MyThread"); RunnableClass = (jclass) env->NewGlobalRef(env->FindClass("java/lang/Runnable")); jfieldID runnableID = env->GetFieldID(MyThreadClass, "mRunnable", "Ljava/lang/Runnable;"); jobject mRunnable = env->NewGlobalRef(env->GetObjectField(thiz, runnableID));
pthread_t tid; int ret_t = -1; ret_t = pthread_create(&tid, NULL, new_thread, mRunnable); pthread_detach(tid); if (ret_t != 0) { printf("pthread_create error \n"); return; } LOGD("java invoke start()---------------end"); return; }
|
java 调用了start方法进入 c 层面,接下来 主要是通过pthread创建新线程,在新线程里面反调java里面的run方法。
新建的线程 void *new_thread(void *arg)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void *new_thread(void *arg) { LOGD("new_thread-----------------"); JNIEnv *env; jobject mRunnable = static_cast<jobject>(arg); LOGD("new_thread-----------------AttachCurrentThread()"); jvm->AttachCurrentThread(&env, NULL); jmethodID run = NULL; LOGD("new_thread-----------------GetMethodID"); run = env->GetMethodID(RunnableClass, "run", "()V"); LOGD("new_thread-----------------CallVoidMethod"); env->CallVoidMethod(mRunnable, run); env->DeleteGlobalRef(mRunnable); LOGD("new_thread-----------------end"); return nullptr; }
|
加载库的时候做一下初始化
1 2 3 4 5 6 7 8 9 10 11
| jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if (JNI_OK != vm->GetEnv((void **) &env, JNI_VERSION_1_6)) { printf("JNI_OnLoad error \n"); return -1; } jvm = vm; LOGD("JNI_OnLoad-----------------------------------"); return JNI_VERSION_1_6; }
|
最后在java 里面加载so文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MyThread { Runnable mRunnable;
static { System.loadLibrary("native-lib"); System.out.println("load native-lib"); }
public MyThread(Runnable runnable) { mRunnable = runnable; }
native public void start(); }
|
测试
1 2 3 4 5 6
| new MyThread(new Runnable() { @Override public void run() { System.out.println("Hello World!"); } }).start();
|
结果
1 2 3 4 5 6 7 8 9 10
| D/native-lib: JNI_OnLoad----------------------------------- I/System.out: load native-lib D/native-lib: java invoke start()---------------start java invoke start()---------------end D/native-lib: new_thread----------------- new_thread-----------------AttachCurrentThread() new_thread-----------------GetMethodID new_thread-----------------CallVoidMethod I/System.out: Hello World! D/native-lib: new_thread-----------------end
|