Android NDK使用之--用pthread实现多线程
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实现多线程相关推荐
- Android NDK JNI C++ 13 pthread多线程
这一篇将初步介绍NDK开发中多线程方面相关操作,具体步骤如下: 多线程采用 POSIX 的pthread方式实现. <1> : 新建一个Android工程 androidpthreadjn ...
- OpenCV使用pthread实现多线程加速处理图像(C++)
OpenCV使用pthread实现多线程加速处理图像 [尊重原创,转载请注明出处]https://blog.csdn.net/guyuealian/article/details/81912704 目 ...
- Android NDK 编译选项设置[zhuan]
http://crash.163.com/#news/!newsId=24 在Android NDK开发中,有两个重要的文件:Android.mk和Application.mk,各尽其责,指导编译器如 ...
- android linux pthread_cancel,Android NDK缺失pthread_cancel和pthread_setcancelstate
Android NDK在v5版本后不再提供全部的POSIX线程库的API(比如pthread_cancel和pthread_setcancelstate).原因之一是线程被标记结束后不一定会把自己拥有 ...
- Win7下利用MinGW和Android NDK编译ffmpeg0.10(neon优化)
不久之前萌生了移植ffmpeg到android平台上的冲动,然后就开始搞.网上搜了个遍,着实费了不少工夫.因此把成果列出来供同道中人参考. 本文主要参考了Scott Wong 兄的在 Windows ...
- 音频之Android NDK读写声卡
通过Android NDK读写声卡通过 AudioRecord和AudioTrack两个类实现. AudioTrack:负责声音数据的输出 AudioRecord:负责声音数据的采集 相关头文件位置 ...
- Android NDK 直播推流与引流,flutterui套件
if (mIsPushing) { mNativePush.fireVideo(bytes); } } 音频采集 音频采集基于 AudioRecord 实现,在一个子线程采集音频 PCM 数据,并将数 ...
- Android ndk 安装教程 以及环境变量配置
现在android ndk 也是非常的方便 第一步 第二步搜索sdk 第三步 把界面切换到SDK Tools 界面 选中ndk 然后在点击Apply 下载即可 然后就是查看ndk 安装到那个目录下面 ...
- Android NDK开发之旅29 云服务器Ubuntu下搭建NDK环境,并编译FFmpeg
###前言 因为在Linux环境下编译FFmpeg生成库和头文件下比较方便,所以接下来主要操作在Linux环境下进行.但是对于Android NDK 开发新手来说,自己电脑配置Ubuntu Linux ...
最新文章
- [NOIP2014] 解方程
- lisp xy轴不等比缩放_不就是用Python做个动态图吗?看招
- qt连接mysql创建表_Qt编译mysql以及创建表后进行导入操作
- Python中机器学习的特征选择工具
- 移植linux内核-映像文件,移植Linux内核-映像文件
- 如果唐朝人拿到一篇现代文章……
- win10连接烟台大学校园网
- div嵌套,内层的margin-top会跑到外层
- java fx 重绘_如何重绘JAVA FX 2.2中的窗口(舞台)
- 通过adb和python直接传输Android截图到电脑(windows适用)
- 进程间通信之FIFO
- 3D点云深度学习综述
- openCV 出现 0x770413C5 (ntdll.dll) 第一机会异常: 0xC0000005: 读取位置 0x00000008 时发生访问冲突 解决办法
- Android后台播放音乐(含通知栏操作)
- 基于HSV颜色空间的辅助车牌定位
- 异方差下的OLS估计无效性
- c语言二级安卓软件,C语言二级考试题库
- 深圳小鹅网络前端校招视频面试
- 读书的意义(知乎的一位大学生毕业奋斗过程)
- f1c100s spi flash分区