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("\n");
}
});
}
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线程运行完毕。