Android NDK programming: Using posix multithreading and mutex Synchronization
MainActivity. java
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; @ Overrideprotected 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 () {@ Overridepublic 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); // use java threads to cycle posixThreads (threads, iterations); // use posix threads} private void javaThreads (int threads, final int iterations) {for (int I = 0; I <threads; I ++) {final int id = I; new Thread () {@ Overridepublic void run () {nativeWorker (id, iterations); super. run ();}}. start () ;}} private void onNativeMessage (final String message) {runOnUiThread (new Runnable () {@ Overridepublic void run () {tvLog. append (message); tvLog. append ("\ n") ;}});} private native void posixThreads (int threads, int iterations); // initialize private native void nativeInit (); // release the memory private native void nativeFree (); // java thread directly calls jniprivate 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 ;}@ Overrideprotected void onDestroy () {nativeFree (); super. onDestroy ();} static {System. loadLibrary ("Threads ");}}
Com_apress_threads_MainActivity.h:
/* DO NOT EDIT THIS FILE - it is machine generated */#include
/* Header for class com_apress_threads_MainActivity */#ifndef _Included_com_apress_threads_MainActivity#define _Included_com_apress_threads_MainActivity#ifdef __cplusplusextern "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:
# Include
# Include
# Include
# Include "com_apress_threads_MainActivity.h" # include # define LOG_TAG "log from jni" # define LOGW (a) _ android_log_write (ANDROID_LOG_WARN, LOG_TAG,) // The struct NativeWorkerArgs {jint id; jint iterations ;}; // callback java method static jmethodID gOnNativeMessage = NULL; static JavaVM * gVm = NULL; // vm reference, which is automatically called when the global variable static jobject gObj = NULL; static pthread_mutex_t mutex; // loadLibrary. Obtain the global vm reference jint JNI_OnLoad (JavaVM * vm, void * reserved) {gVm = vm; LOGW ("JNI_OnLoad"); return JNI_VERSION_1_4;} void Merge (JNIEnv * env, jobject obj) {// initialize the mutex if (0! = Pthread_mutex_init (& mutex, NULL) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException"); // throw env-> ThrowNew (exceptionClazz, "Unable to init mutex --");} if (NULL = gObj) {gObj = env-> NewGlobalRef (obj );} // initial java callback if (NULL = gOnNativeMessage) {jclass clazz = env-> GetObjectClass (obj); gOnNativeMessage = env-> GetMethodID (clazz, "onNativeMessage ", "(Ljava/lang/String;) V"); if (NULL = g OnNativeMessage) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException"); // throw env-> ThrowNew (exceptionClazz, "Unable to find method --") ;}} void Java_com_apress_threads_MainActivity_nativeFree (JNIEnv * env, jobject) {// release the global variable if (NULL! = GObj) {env-> DeleteGlobalRef (gObj); gObj = NULL;} // release the mutex if (0! = Pthread_mutex_destroy (& mutex) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException"); // throw env-> ThrowNew (exceptionClazz, "Unable to destroy mutex --") ;}// void nativeWorker (JNIEnv * env, jobject obj, jint id, jint iterations) of the Code executed by the ndk thread) {// lockif (0! = Pthread_mutex_lock (& mutex) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException"); // throw 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); // callback java method jstring messageString = env-> NewStringUTF (message); env-> CallVoidMethod (obj, gOnNativeMessage, messageString); if (NULL! = Env-> predictionoccurred () {break;} sleep (1);} // unlockif (0! = Pthread_mutex_unlock (& mutex) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException"); // throw env-> ThrowNew (exceptionClazz, "Unable to unlock mutex --") ;}} void Merge (JNIEnv * env, jobject obj, jint id, jint iterations) {nativeWorker (env, obj, id, iterations );} // method of pthread execution static void * nativeWorkerThread (void * args) {JNIEnv * env = NULL; if (0 = GVm-> AttachCurrentThread (& env, NULL) {NativeWorkerArgs * nativeWorkerAgrs = (optional *) args; // nativeWorker (env, gObj, nativeWorkerAgrs-> id, nativeWorkerAgrs-> iterations); delete nativeWorkerAgrs; gVm-> DetachCurrentThread ();} return (void *) 1;} // called by java, start Multiple threads void Java_com_apress_threads_MainActivity_posixThreads (JNIEnv * env, jobject obj, jint threads, jint iterations) {// thread handlerspthr Ead_t * handles = new pthread_t [threads]; // start the thread for (jint I = 0; I <threads; I ++) {// thread argumentsNativeWorkerArgs * nativeWorkArgs = new NativeWorkerArgs (); nativeWorkArgs-> id = I; nativeWorkArgs-> iterations = iterations; // thread handlerint result = pthread_create (& handles [I], NULL, nativeWorkerThread, (void *) nativeWorkArgs); if (result! = 0) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException"); // throw env-> ThrowNew (exceptionClazz, "Unable to create thread --"); return ;}// thread running result for (jint I = 0; I <threads; I ++) {void ** result = NULL; if (0! = Pthread_join (handles [I], result) {// exception jclass exceptionClazz = env-> FindClass ("java/lang/RuntimeException "); // throw 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-> predictionoccurred () {return ;}}}}
Download: http://download.csdn.net/detail/hai836045106/7986143