Android系统本身包括Java和Linux内核;因此在Android应用中实现多线程就可以是基于Java上的和基于Linux上的;今天本文介绍的就是Android利用Linux下的pthread来实现多线程;大概思路如下:
我们将异步任务需要实现的方法在Java中定义,但是运行异步任务的线程交给pthread实现;
因此首先设计一个接口,作为异步任务的业务接口:

//异步任务业务接口
public interface LocalRunnable {public void run();
}

定义本地方法


/*** * @author 徐晔 线程池*/
public class ThreadPool {static {System.loadLibrary("threadpool");}/** 初始化本地线程池 */public native void init();/** 本地线程中执行任务 */public native int run(LocalRunnable runnable);/**释放资源*/public native void recycle();
}

通过本地方法类生成的.h文件如下:

     com_localThread_ThreadPool.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
//实现pthread需要包括的接口
#include <unistd.h>
#include <pthread.h>
/* Header for class com_localThread_ThreadPool */#ifndef _Included_com_localThread_ThreadPool
#define _Included_com_localThread_ThreadPool
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     com_localThread_ThreadPool* Method:    init* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_localThread_ThreadPool_init(JNIEnv *, jobject);/** Class:     com_localThread_ThreadPool* Method:    run* Signature: (Lcom/localThread/LocalRunnable;)I*/
JNIEXPORT jint JNICALL Java_com_localThread_ThreadPool_run(JNIEnv *, jobject,jobject);/** Class:     com_localThread_ThreadPool* Method:    recycle* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_localThread_ThreadPool_recycle(JNIEnv *,jobject);#ifdef __cplusplus
}
#endif
#endif

具体的实现代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "com_localThread_ThreadPool.h"
/* Header for class com_localThread_ThreadPool */static JavaVM *jvm = NULL;
static jobject jobj = NULL;
static jmethodID mid = NULL;
static int flag = -1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//在加载库时执行
jint JNI_OnLoad(JavaVM *vm, void *reserved) {jvm = vm;return JNI_VERSION_1_6;
}
//在卸载库时执行
void JNI_OnUnLoad(JavaVM *vm, void *reserved) {jvm = NULL;
}
//pthread中执行的函数
void *nativeWork(void *args) {JNIEnv *env = NULL;//将本地线程连接到虚拟机上,这样本地线程才对虚拟机可见并且可以访问到虚拟机所在进程的资源if (0 == jvm->AttachCurrentThread(&env, NULL)) {while (flag == 0) {if (jobj == NULL) {//进入等待pthread_cond_wait(&cond, &mutex);} else {//执行方法env->CallVoidMethod(jobj, mid);env->DeleteGlobalRef(jobj);jobj = NULL;}}jvm->DetachCurrentThread();}return (void *) 1;
}/** Class:     com_localThread_ThreadPool* Method:    init* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_localThread_ThreadPool_init(JNIEnv * env,jobject obj) {if (NULL == mid) {//缓存方法jclass cls = env->FindClass("com/localThread/LocalRunnable");mid = env->GetMethodID(cls, "run", "()V");if (mid == NULL) {return;}flag = 0;pthread_t thread;//创建新线程pthread_create(&thread, NULL, nativeWork, NULL);}
}/** Class:     com_localThread_ThreadPool* Method:    run* Signature: (Lcom/localThread/LocalRunnable;)I*/
JNIEXPORT jint JNICALL Java_com_localThread_ThreadPool_run(JNIEnv * env,jobject obj, jobject callback) {//设置参数,唤醒等待的线程flag=0;jobj = env->NewGlobalRef(callback);return pthread_cond_signal(&cond);
}/** Class:     com_localThread_ThreadPool* Method:    recycle* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_localThread_ThreadPool_recycle(JNIEnv * env,jobject obj) {//释放资源flag = -1;env->DeleteGlobalRef(jobj);
}

Java层对本地线程类的一个封装:


public class ThreadPoolRun {/** 利用阻塞队列保存任务 */private static LinkedBlockingDeque<BaseLocalRunnable> runnables = new LinkedBlockingDeque<BaseLocalRunnable>();private BaseLocalRunnable lr = null;public static ThreadPoolRun instance = new ThreadPoolRun();private ThreadPool pool = null;boolean runflag = false;private ThreadPoolRun() {pool = new ThreadPool();pool.init();}/** 添加任务 */public void addTask(BaseLocalRunnable runnable) {runnables.addLast(runnable);}/** 取出任务 */private BaseLocalRunnable getTask() {try {return runnables.removeFirst();} catch (Exception e) {e.printStackTrace();return null;}}public void runTask() {synchronized (pool) {lr = getTask();if (lr != null && !runflag) {runflag = true;lr.before(lr.taskid);pool.run(lr);}}}//当每次执行完成上一个任务后,设置标示,运行下一个任务public void runend() {runflag = false;runTask();}
}

实现基本任务类:


public abstract class BaseLocalRunnable implements LocalRunnable, MainRunnable {private Handler mainHandler;private MainRunnable mainRunnable;int taskid;public BaseLocalRunnable(Handler mainHandler, MainRunnable mainRunnable) {this.mainHandler = mainHandler;this.mainRunnable = mainRunnable;}@Overridepublic final void run() {onfinished(dobackground(), taskid);}public final void execute(int taskid) {ThreadPoolRun.instance.addTask(this);this.taskid = taskid;if (!ThreadPoolRun.instance.runflag) {ThreadPoolRun.instance.runTask();}}public abstract Object dobackground();@Overridepublic final void onfinished(final Object object, final int raskid) {mainHandler.post(new Runnable() {@Overridepublic void run() {if (mainRunnable != null) {mainRunnable.onfinished(object, raskid);}// 读取下一个信息ThreadPoolRun.instance.runend();}});}@Overridepublic final void before(int id) {if (mainRunnable != null) {mainRunnable.before(id);}}}

主类需要实现的接口:


public interface MainRunnable {public void before(int id);public void onfinished(Object object, int raskid);}

测试代码:


public class Task extends BaseLocalRunnable {public Task(Handler mainHandler, MainRunnable mainRunnable) {super(mainHandler, mainRunnable);}@Overridepublic Object dobackground() {try {Thread.sleep(3000);} catch (Exception e) {e.printStackTrace();}return "执行完成";}}public class TestActivity extends Activity implements MainRunnable {private TextView text;private Button am_button;private Handler mainHandler = null;private Task task;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mainHandler = new Handler(getMainLooper());text = (TextView) findViewById(R.id.text);am_button = (Button) findViewById(R.id.am_button);am_button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {task = new Task(mainHandler, TestActivity.this);task.execute(0);}});}@Overridepublic void before(int id) {Log.v("任务", id + "开启");}@Overridepublic void onfinished(Object object, int taskid) {Log.v("结果", "结束" + object.toString());}
}

运行结果如下:我连续点击了几次按钮,出现的结果是一次一次执行

Android NDK使用之--用pthread实现多线程相关推荐

  1. Android NDK JNI C++ 13 pthread多线程

    这一篇将初步介绍NDK开发中多线程方面相关操作,具体步骤如下: 多线程采用 POSIX 的pthread方式实现. <1> : 新建一个Android工程 androidpthreadjn ...

  2. OpenCV使用pthread实现多线程加速处理图像(C++)

    OpenCV使用pthread实现多线程加速处理图像 [尊重原创,转载请注明出处]https://blog.csdn.net/guyuealian/article/details/81912704 目 ...

  3. Android NDK 编译选项设置[zhuan]

    http://crash.163.com/#news/!newsId=24 在Android NDK开发中,有两个重要的文件:Android.mk和Application.mk,各尽其责,指导编译器如 ...

  4. android linux pthread_cancel,Android NDK缺失pthread_cancel和pthread_setcancelstate

    Android NDK在v5版本后不再提供全部的POSIX线程库的API(比如pthread_cancel和pthread_setcancelstate).原因之一是线程被标记结束后不一定会把自己拥有 ...

  5. Win7下利用MinGW和Android NDK编译ffmpeg0.10(neon优化)

    不久之前萌生了移植ffmpeg到android平台上的冲动,然后就开始搞.网上搜了个遍,着实费了不少工夫.因此把成果列出来供同道中人参考. 本文主要参考了Scott Wong 兄的在 Windows ...

  6. 音频之Android NDK读写声卡

    通过Android NDK读写声卡通过 AudioRecord和AudioTrack两个类实现. AudioTrack:负责声音数据的输出 AudioRecord:负责声音数据的采集 相关头文件位置 ...

  7. Android NDK 直播推流与引流,flutterui套件

    if (mIsPushing) { mNativePush.fireVideo(bytes); } } 音频采集 音频采集基于 AudioRecord 实现,在一个子线程采集音频 PCM 数据,并将数 ...

  8. Android ndk 安装教程 以及环境变量配置

    现在android ndk 也是非常的方便 第一步 第二步搜索sdk 第三步 把界面切换到SDK Tools 界面 选中ndk  然后在点击Apply 下载即可 然后就是查看ndk 安装到那个目录下面 ...

  9. Android NDK开发之旅29 云服务器Ubuntu下搭建NDK环境,并编译FFmpeg

    ###前言 因为在Linux环境下编译FFmpeg生成库和头文件下比较方便,所以接下来主要操作在Linux环境下进行.但是对于Android NDK 开发新手来说,自己电脑配置Ubuntu Linux ...

最新文章

  1. Educational Codeforces Round 45 (Rated for Div. 2) D Graph And Its Complement(图的构造)
  2. 第四范式联合浪潮商用机器发布AI一体机,接入AI像使用手机一样简单
  3. STAR: ultrafast universal RNA-seq aligner STAR:超快的通用RNA-seq比对器
  4. 2021年春季学期-信号与系统-第五次作业参考答案-第七小题
  5. PL/SQL developer连接oracle出现“ORA-12154:TNS:could not resolve the connect identifier specified”问题的解决
  6. 用C语言实现三子棋游戏
  7. java 操作 mongodb_Java操作MongoDB数据库方法详解
  8. 苹果秋季新品将要发布,MacBook Pro都有哪些变化
  9. 黄轩成为QQ阅读新代言人 变身“队长”号召网友 “组队读书”
  10. python安装sql模块_在Python安装MySQL支持模块的方法
  11. python爬虫之伪装浏览器
  12. 如何使用matlab进行音频信号处理+代码编译中会遇到的问题+matlab安装包
  13. jsp主板 jtp_HPlaserjtp1008不开机故障的检测与维修流程
  14. ELK安装( Elasticsearch、Logstash、Kibana)
  15. 计算机数学与高中数学衔接,浅谈如何做好高中数学与大学数学的衔接
  16. 网络安全风险评估关键技术讨论
  17. 计算机毕业设计-校园疫情防控系统【PHP源码】
  18. js可以打开mat文件吗_企业微信最大可以传多大文件?企业微信发送文件有限制吗?...
  19. 苹果CMS V8 韩剧TV 一款特别精美漂亮的模板 包含PC端+WAP端
  20. 学了深度学习能干什么?飞桨内推岗位大曝光!

热门文章

  1. HanLp的RESTful部分
  2. (转)Windows Server 2008 默认"照片库查看器" 无法打开图片, 只能用画图程序打开...
  3. UE5灯光蓝图和思路
  4. java lambda 是什么_自己理解Java中的lambda
  5. 新概念2 课文和单词(18)
  6. 做设计专业太卷了想转行,做什么工作前景更好更赚米?
  7. 10086视频客服所需要的技能点
  8. python字符串大写字母个数_【python实例】统计字符串里大写字母,小写字母的个数和非字母的个数...
  9. 英特尔IA-32读书笔记2
  10. java202303java学习笔记第四十三天函数-四大特性SCID