Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android NDK編程:使用posix多線程與mutex互斥同步

android NDK編程:使用posix多線程與mutex互斥同步

編輯:關於Android編程

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;

	@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 
/* 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:

#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,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;
			}
		}
	}

}

代碼下載: http://download.csdn.net/detail/hai836045106/7986143

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved