MainActivity.java
调用原生方法 posixThreads(int threads, int iterations) 启动线程
package com.apress.threads; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity { private EditText editThreads; private EditText editIterations; private Button btnStart; private TextView tvLog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); nativeInit(); editThreads = (EditText) findViewById(R.id.threads_edit); editIterations = (EditText) findViewById(R.id.iterations_edit); btnStart = (Button) findViewById(R.id.start_button); tvLog = (TextView) findViewById(R.id.log_view); btnStart.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int threads = getNumber(editThreads, 0); int iterations = getNumber(editIterations, 0); if (threads > 0 && iterations > 0) { startThreads(threads, iterations); } } }); } private void startThreads(int threads, int iterations) { // javaThreads(threads, iterations);//使用java的线程来循环 posixThreads(threads, iterations);// 使用posix线程 } private void javaThreads(int threads, final int iterations) { for (int i = 0; i < threads; i++) { final int id = i; new Thread() { @Override public void run() { nativeWorker(id, iterations); super.run(); } }.start(); } } private void onNativeMessage(final String message) { runOnUiThread(new Runnable() { @Override public void run() { tvLog.append(message); tvLog.append(" "); } }); } private native void posixThreads(int threads, int iterations); // 初始化 private native void nativeInit(); // 释放内存 private native void nativeFree(); // java线程直接调用jni private native void nativeWorker(int id, int iterations); private static int getNumber(EditText editText, int defaultValue) { int value; try { value = Integer.parseInt(editText.getText().toString()); } catch (Exception e) { value = defaultValue; } return value; } @Override protected void onDestroy() { nativeFree(); super.onDestroy(); } static { System.loadLibrary("Threads"); } }
com_apress_threads_MainActivity.h:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_apress_threads_MainActivity */ #ifndef _Included_com_apress_threads_MainActivity #define _Included_com_apress_threads_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: com_apress_threads_MainActivity * Method: posixThreads * Signature: (II)V */ JNIEXPORT void JNICALL Java_com_apress_threads_MainActivity_posixThreads (JNIEnv *, jobject, jint, jint); /* * Class: com_apress_threads_MainActivity * Method: nativeInit * Signature: ()V */ JNIEXPORT void JNICALL Java_com_apress_threads_MainActivity_nativeInit (JNIEnv *, jobject); /* * Class: com_apress_threads_MainActivity * Method: nativeFree * Signature: ()V */ JNIEXPORT void JNICALL Java_com_apress_threads_MainActivity_nativeFree (JNIEnv *, jobject); /* * Class: com_apress_threads_MainActivity * Method: nativeWorker * Signature: (II)V */ JNIEXPORT void JNICALL Java_com_apress_threads_MainActivity_nativeWorker (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
com_apress_threads_MainActivity.cpp:
在java层调用到原生方法Java_com_apress_threads_MainActivity_posixThreads后。封装參数,调用pthread_create创建线程,使用pthread_join监听线程执行结果并回调到java层。
线程指向的函数为void* nativeWorkerThread(void* args),在这个函数里将native线程通过JNI来attach到Java环境里,这样native线程才干够使用JNIEnv。运行完成后要Detach。详细说明可參考http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/invocation.html#attach_current_thread
native线程调用nativeWorker函数输出字符串。通过JNIEnv回调java方法。
在初始化方法中初始化JavaVM* gVm,用来attach到虚拟机中。
#include <stdio.h> #include <unistd.h> #include <pthread.h> #include "com_apress_threads_MainActivity.h" #include <android/log.h> #define LOG_TAG "LOG FROM JNI" #define LOGW(a) __android_log_write(ANDROID_LOG_WARN,LOG_TAG,a) //传递pthread參数用的结构体 struct NativeWorkerArgs { jint id; jint iterations; }; //回调java的方法 static jmethodID gOnNativeMessage = NULL; static JavaVM* gVm = NULL; //虚拟机引用,作为全局变量 static jobject gObj = NULL; static pthread_mutex_t mutex; //loadLibrary的时候自己主动调用,在这里获得全局vm引用 jint JNI_OnLoad(JavaVM* vm, void* reserved) { gVm = vm; LOGW("JNI_OnLoad"); return JNI_VERSION_1_4; } void Java_com_apress_threads_MainActivity_nativeInit(JNIEnv *env, jobject obj) { //初始化相互排斥量 if (0 != pthread_mutex_init(&mutex, NULL)) { //异常 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to init mutex--"); } if (NULL == gObj) { gObj = env->NewGlobalRef(obj); } //初始java回调 if (NULL == gOnNativeMessage) { jclass clazz = env->GetObjectClass(obj); gOnNativeMessage = env->GetMethodID(clazz, "onNativeMessage", "(Ljava/lang/String;)V"); if (NULL == gOnNativeMessage) { //异常 jclass exceptionClazz = env->FindClass( "java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to find method--"); } } } void Java_com_apress_threads_MainActivity_nativeFree(JNIEnv *env, jobject) { //释放全局变量 if (NULL != gObj) { env->DeleteGlobalRef(gObj); gObj = NULL; } //释放相互排斥量 if (0 != pthread_mutex_destroy(&mutex)) { //异常 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to destroy mutex--"); } } //ndk线程运行的代码 void nativeWorker(JNIEnv *env, jobject obj, jint id, jint iterations) { //lock if (0 != pthread_mutex_lock(&mutex)) { //异常 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to lock mutex--"); return; } for (jint i = 0; i < iterations; i++) { char message[26]; sprintf(message, "Worker %d:Iteration %d", id, i); //回调java方法 jstring messageString = env->NewStringUTF(message); env->CallVoidMethod(obj, gOnNativeMessage, messageString); if (NULL != env->ExceptionOccurred()) { break; } sleep(1); } //unlock if (0 != pthread_mutex_unlock(&mutex)) { //异常 jclass exceptionClazz = env->FindClass("java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to unlock mutex--"); } } void Java_com_apress_threads_MainActivity_nativeWorker(JNIEnv *env, jobject obj, jint id, jint iterations) { nativeWorker(env, obj, id, iterations); } //pthread运行的方法 static void* nativeWorkerThread(void* args) { JNIEnv* env = NULL; if (0 == gVm->AttachCurrentThread(&env, NULL)) { NativeWorkerArgs* nativeWorkerAgrs = (NativeWorkerArgs*) args; // nativeWorker(env, gObj, nativeWorkerAgrs->id, nativeWorkerAgrs->iterations); delete nativeWorkerAgrs; gVm->DetachCurrentThread(); } return (void*) 1; } //java调用的。启动多个线程 void Java_com_apress_threads_MainActivity_posixThreads(JNIEnv *env, jobject obj, jint threads, jint iterations) { //thread handlers pthread_t* handles = new pthread_t[threads]; //启动线程 for (jint i = 0; i < threads; i++) { //thread arguments NativeWorkerArgs* nativeWorkArgs = new NativeWorkerArgs(); nativeWorkArgs->id = i; nativeWorkArgs->iterations = iterations; //thread handler int result = pthread_create(&handles[i], NULL, nativeWorkerThread, (void*) nativeWorkArgs); if (result != 0) { //异常 jclass exceptionClazz = env->FindClass( "java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to create thread--"); return; } } //线程运行结果 for (jint i = 0; i < threads; i++) { void** result = NULL; if (0 != pthread_join(handles[i], result)) { //异常 jclass exceptionClazz = env->FindClass( "java/lang/RuntimeException"); //抛出 env->ThrowNew(exceptionClazz, "Unable to join thread--"); } else { char message[26]; sprintf(message, "Worker %d:return %d", i, result); jstring messageString = env->NewStringUTF(message); env->CallVoidMethod(obj, gOnNativeMessage, messageString); if (NULL != env->ExceptionOccurred()) { return; } } } }
这里执行的时候会堵塞界面,直接全部native线程执行完成。