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 ...
随机推荐
- 深入浅出Mysql索引
索引的出现其实就是为了提高数据查询的效率,就像书的目录一样. 索引模型有三种常见.也比较简单的数据结构分别是哈希表.有序数组和搜索树. 哈希表 哈希表是一种以键 - 值(key-value)存储数据的 ...
- 用JDK自带的监控工具jconsole来监控程序运行
工具目录:C:\Program Files\Java\jdk1.6.0_06\bin\jconsole.exe 效果如下:监控类ThreadPoolExecutorTest 的运行 选择我们运行的程序 ...
- C# HTML 生成 PDF
原文出处:http://www.cnblogs.com/shanyou/archive/2012/09/07/2676026.html
- JavaScript 七种数据类型
在 JavaScript 规范中,共定义了七种数据类型,分为 “基本类型” 和 “引用类型” 两大类,如下所示: 基本类型:String.Number.Boolean.Symbol.Undefined ...
- jquery validate表单验证插件的基本使用方法及功能拓展
1 表单验证的准备工作 在开启长篇大论之前,首先将表单验证的效果展示给大家. 1.点击表单项,显示帮助提示 2.鼠标离开表单项时,开始校验元素 3.鼠标离开后的正确.错误提示及鼠标移入时的帮助提 ...
- Qt Installer Framework实战
Qt Installer Framework是Qt发布的安装程序支持框架,只需要简单的配置就可以生成安装文件,同时可以通过javascript脚本来定制安装过程. 目录结构 config packag ...
- wc 统计行数 字数
Linux统计文件行数 2011-07-17 17:32 by 依水间, 168255 阅读, 4 评论, 收藏, 编辑 语法:wc [选项] 文件… 说明:该命令统计给定文件中的字节数.字数.行数. ...
- Linux-数据库1
数据库介绍 数据库(database,DB)是指长期存储在计算机内的,有组织,可共享的数据的集合.数据库中的数据按一定的数学模型组织.描述和存储,具有较小的冗余,较高的数据独立性和易扩展性,并可为各种 ...
- OpenStack openvswitch 实践
先说下我这架构就是2个节点控制节点+计算节点,网络这采用ovs方法没有路由,就是二层打通并且可以多vlan. 网络架构图: eth0网卡走trunk,走多vlan.从dashboard上创建不同的vl ...
- 深度理解python中的元类
本文转自:(英文版)https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python (翻译版) http:// ...