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. [NOIP2014] 解方程
  2. lisp xy轴不等比缩放_不就是用Python做个动态图吗?看招
  3. qt连接mysql创建表_Qt编译mysql以及创建表后进行导入操作
  4. Python中机器学习的特征选择工具
  5. 移植linux内核-映像文件,移植Linux内核-映像文件
  6. 如果唐朝人拿到一篇现代文章……
  7. win10连接烟台大学校园网
  8. div嵌套,内层的margin-top会跑到外层
  9. java fx 重绘_如何重绘JAVA FX 2.2中的窗口(舞台)
  10. 通过adb和python直接传输Android截图到电脑(windows适用)
  11. 进程间通信之FIFO
  12. 3D点云深度学习综述
  13. openCV 出现 0x770413C5 (ntdll.dll) 第一机会异常: 0xC0000005: 读取位置 0x00000008 时发生访问冲突 解决办法
  14. Android后台播放音乐(含通知栏操作)
  15. 基于HSV颜色空间的辅助车牌定位
  16. 异方差下的OLS估计无效性
  17. c语言二级安卓软件,C语言二级考试题库
  18. 深圳小鹅网络前端校招视频面试
  19. 读书的意义(知乎的一位大学生毕业奋斗过程)
  20. f1c100s spi flash分区

热门文章

  1. Django表单之ModelForm实践
  2. 当OLTP数据库遇上分布式存储,我选择走一条难而正确的路
  3. java hsv_HSV颜色空间
  4. 有容乃大,无欲则刚,容是别人,欲是自己
  5. ELF文件详解 ---- 初步认识
  6. 手机安装Ubuntu搭建web服务器
  7. 涂鸦风潮–手绘元素的魅力【视觉设计】
  8. vsftpd写入延误_延误成本:为什么要当心,第6部分
  9. Office_00000
  10. matlab toolbox 安装,matlab中robot toolbox 下载安装