android NDK编程:使用posix多线程与mutex相互排斥同步
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线程执行完成。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFpODM2MDQ1MTA2/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="480" height="800" alt="">
android NDK编程:使用posix多线程与mutex相互排斥同步的更多相关文章
- 三、Android NDK编程预备之Java jni入门创建C/C++共享库
转自: http://www.eoeandroid.com/thread-264971-1-1.html 应网友回复,答应在两天前要出一篇创建C/C++共享库的,但由于清明节假期,跟朋友出去游玩,丢手 ...
- 二、Android NDK编程预备之Java jni入门Hello World
转自: http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...
- 一、Android NDK编程预备之Java jni简介
转自: http://www.eoeandroid.com/thread-264384-1-1.html 游戏开发 视频教程 博客 淘帖 论坛›eoe·Android应用开发区›Androi ...
- Android NDK编程,引入第三方.so库
android自带的编译工具NDK进行编译时(非单纯的调用第三方.so而是进行ndk编程),armeabi以及armeabi-v7a文件夹下的第三方so文件将会被删除,只会产生编译后的so文件,其他的 ...
- (转)Android: NDK编程入门笔记
转自: http://www.cnblogs.com/hibraincol/archive/2011/05/30/2063847.html 为何要用到NDK? 概括来说主要分为以下几种情况: 1. 代 ...
- Android NDK编程浅入深出之--Android.mk
Android.mk Android.mk是一个向Android NDK构建系统描写叙述NDK项目的GUN Makefile片段.它是每个NDK项目的必备组件. 构建系统希望它出如今jni子文 ...
- Android NDK编程
1.首先需要声明native方法: public native String helloWorldNdk(); public native String hello_World_Ndk(); 2.然后 ...
- POSIX多线程
全文共分四部分: POSIX多线程—概述 POSIX多线程—异步编程举例 POSIX多线程—线程基本概念 POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. ...
- Android NDK学习总结
一.android NDK编程步骤 java文件中声明native方法. android工程根目录新建jni文件夹. 调用javah命令为第一步声明的native方法生成相应的.h头文件. 通过win ...
随机推荐
- 配置OpenCV+VS2013环境
配置OpenCV+VS2013环境 准备工作 win7系统 下载opencv的windows编译版 安装vs2013 express 设定环境变量 按windows窗键输入path,选择第二个结果编辑 ...
- 【hdoj_1715】大菲波数(大数+100000000进制)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1715 本题采用大数加法即可解决.采用100000000进制速度更快. C++代码如下: #include& ...
- 【PAT】1011. A+B和C (15)
1011. A+B和C (15) 给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测 ...
- VuGen录制选项Recording Options
- 在 Ubuntu 系统安装 Redi laravel 5.2 引入第三方类
composer 安装类依赖包 很受用 也很方便 但是要是一个有一定规模的公司技术团队 因为要照顾大局 还是引入类好些 下面是引入类的方法 1.首先在app目录下创建一个新的文件夹,命名Tools(可 ...
- Socket 异步
摘要: System.Net.Sockets.Sockte 类有一组增强功能,提供可供专用的高性能套接字应用程序使用的可选异步模式,SocketAsyncEventArgs 类就是这一组增强功能的一部 ...
- jQuery.Validate.js验证大表单的优化
最近在项目中有遇到一个Form表单中有200多个标签.在提交表单时网页会出现等待时间很长,甚至会出现网页奔溃的情况. 主要的原因是因为在使用jQuery.Validate.js进行Form验证的时候会 ...
- JSTL-2
流程控制标签:if标签, choose标签, when标签, otherwise标签 <c:if>:的两种语法 1.<c:if test="" var=&qu ...
- Vue 2.0学习(四)计算属性
{{}}模板内的表达式常用于简单的运算,当运算过长或逻辑复杂时,会难以维护. <div> {{ text.split(',').reverse().join('') }} </div ...
- -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】
[把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...