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 __cplusplusextern "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());}}
运行结果如下:我连续点击了几次按钮,出现的结果是一次一次执行