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="">

代码下载: http://download.csdn.net/detail/hai836045106/7986143

android NDK编程:使用posix多线程与mutex相互排斥同步的更多相关文章

  1. 三、Android NDK编程预备之Java jni入门创建C/C++共享库

    转自: http://www.eoeandroid.com/thread-264971-1-1.html 应网友回复,答应在两天前要出一篇创建C/C++共享库的,但由于清明节假期,跟朋友出去游玩,丢手 ...

  2. 二、Android NDK编程预备之Java jni入门Hello World

    转自:  http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...

  3. 一、Android NDK编程预备之Java jni简介

    转自:  http://www.eoeandroid.com/thread-264384-1-1.html 游戏开发 视频教程 博客 淘帖     论坛›eoe·Android应用开发区›Androi ...

  4. Android NDK编程,引入第三方.so库

    android自带的编译工具NDK进行编译时(非单纯的调用第三方.so而是进行ndk编程),armeabi以及armeabi-v7a文件夹下的第三方so文件将会被删除,只会产生编译后的so文件,其他的 ...

  5. (转)Android: NDK编程入门笔记

    转自: http://www.cnblogs.com/hibraincol/archive/2011/05/30/2063847.html 为何要用到NDK? 概括来说主要分为以下几种情况: 1. 代 ...

  6. Android NDK编程浅入深出之--Android.mk

        Android.mk Android.mk是一个向Android NDK构建系统描写叙述NDK项目的GUN Makefile片段.它是每个NDK项目的必备组件. 构建系统希望它出如今jni子文 ...

  7. Android NDK编程

    1.首先需要声明native方法: public native String helloWorldNdk(); public native String hello_World_Ndk(); 2.然后 ...

  8. POSIX多线程

    全文共分四部分: POSIX多线程—概述    POSIX多线程—异步编程举例    POSIX多线程—线程基本概念    POSIX多线程—互斥量概述 POSIX多线程—概述 Content 1. ...

  9. Android NDK学习总结

    一.android NDK编程步骤 java文件中声明native方法. android工程根目录新建jni文件夹. 调用javah命令为第一步声明的native方法生成相应的.h头文件. 通过win ...

随机推荐

  1. hdu 5505(数论-gcd的应用)

    GT and numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  2. git团队开发

    用git有一年了,下面是我这一年来的git使用总结,覆盖了日常使用中绝大多数的场景.嗯,至少是够用一年了,整理出来分享给大家,不明白的地方可以回复交流. git设置关闭自动换行 git config ...

  3. [实战]MVC5+EF6+MySql企业网盘实战(7)——文件上传

    写在前面 周末了,在家继续折腾网盘,今天实现网盘文件的上传. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企业网盘实战(1) [实战] ...

  4. 易普优APS 5.0高级计划排程系统助力工业4.0智能工厂建设

    (一)智能工厂建设核心 <中国制造2025>明确提出要推进制造过程智能化,智能工厂是实现智能制造的重要载体.作为智能工厂,在生产过程应实现自动化.透明化.可视化.精益化的同时,产品检测.质 ...

  5. 火狐 firefox proxy moz=proxy:// 407错误 解决办法

    设置代理后,访问任一网站均弹窗要求输入代理的用户名和密码,但是多次输入始终无法认证. 最后才发现原来firefox把代理服务器的认证信息当成网站的认证信息记录了. 解决方法:将已登录信息中的代理相关的 ...

  6. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) E - Goods transportation 最大流转最小割转dp

    E - Goods transportation 思路:这个最大流-> 最小割->dp好巧妙哦. #include<bits/stdc++.h> #define LL long ...

  7. 【SQL SERVER】T-SQL 字符串前加 N 是什么意思

    比如 select @status = N'stopped' 那么其中的字符串 stopped 前面为什么要加 N 呢?而且我们发现有些地方加 N 与否都没有影响,有些地方又必须加 N. N 在这里表 ...

  8. ref:【干货分享】PHP漏洞挖掘——进阶篇

    ref:http://blog.nsfocus.net/php-vulnerability-mining/ [干货分享]PHP漏洞挖掘——进阶篇 王陶然     从常见的PHP风险点告诉你如何进行PH ...

  9. IDA问题相关

    1.当想使用F5时出现“please position the cursor within a function”,那么就创建函数,但是创建时出现“The function has undefined ...

  10. 《大话设计模式》--UML图

    类图分三层: 第一层:类的名称,如果是抽象类,就用斜体显示 第二层:类的特性,通常是字段和属性 第三层:类的操作,通常是方法或行为 接口图:第一行是接口名称,第二行是接口方法 继承:用空心三角形+实线 ...