1. 程式人生 > >Android NDK執行緒篇(四)

Android NDK執行緒篇(四)

Android NDK執行緒篇

前言

本篇重點介紹原生執行緒的相關知識,包括執行緒基礎知識,執行緒同步等,學完本篇,你將會對NDK原生執行緒有一個更加深入的認識。

執行緒基礎

執行緒是程序併發執行多工的機制,執行緒可以共享程序的各種資源,程序內的多個執行緒之間可以相互通訊,也可以通過一定的方式進行執行緒,比如互斥鎖,訊號量等。

原生執行緒

我們可以通過Java執行緒來執行原生程式碼,也可以通過原生執行緒來執行。

Java執行緒

Java執行緒基礎

我們可以通過Thread類來建立Java執行緒,也可以通過執行緒池來建立Java執行緒。

Java執行緒同步

本小節重點介紹原生程式碼使用Java物件進行執行緒同步。

原生程式碼可以通過MonitorEnterMonitorExit函式來使用Java物件進行執行緒同步。

示例如下:

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_jniLock(JNIEnv* env, jobject thiz,jobject obj) {
env->MonitorEnter(obj);
//do something
env->MonitorExit(obj);
}

POSIX執行緒

POSIX執行緒基礎

Android NDK的執行緒是通過POSIX標準實現的,所以也叫POSIX

執行緒。POSIX執行緒簡稱pthreads

執行緒標頭檔案

#include <pthread.h>

POSIX執行緒函式
執行緒建立函式
int pthread_create(pthread_t *thread, pthread_attr_t const * attr,

void *(*start_routine)(void *), void * arg);

函式解釋:

thread引數代表pthread_t型別的執行緒指標

attr引數代表執行緒的屬性指標

start_routine引數代表執行緒的執行函式的指標

arg引數代表要傳入執行緒可執行函式的引數

執行緒等待函式
int 
pthread_join(pthread_t thid, void ** ret_val);

函式解決:

thid引數代表pthread_t執行緒

ret_val代表執行緒可執行函式返回值的指標

執行緒退出函式
void pthread_exit(void * retval);

函式解釋:

retval代表執行緒要返回的值

示例程式碼
void * threadFunc(void *arg){

int count=*(int*)arg;

for(int i=0;i<count;i++){

__android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i);

}

return (void *) 0;

}



extern "C"

JNIEXPORT void JNICALL

Java_com_kgdwbb_jnistudy_MainActivity_startNativeThread(JNIEnv* env, jobject thiz,jint count) {

pthread_t pthread;

int *arg=new int(count);

pthread_create(&pthread,NULL,threadFunc,arg);

int *retvalue=0;

pthread_join(pthread,(void**)*retvalue);

if(*retvalue!=0){

__android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred");

}

}

POSIX執行緒同步

POSIX執行緒目前支援兩種執行緒同步方式,分別是互斥體和訊號量,下面分別介紹這兩種執行緒同步方式。

互斥體Mutex
標頭檔案

#include <pthread.h>

函式宣告

Mutex初始化函式

int pthread_mutex_init(pthread_mutex_t *mutex,

const pthread_mutexattr_t *attr);
函式解釋:
mutext引數代表要建立的互斥體指標
attr引數代表要建立的互斥體的屬性,可以為NULL

Mutex鎖定函式

int pthread_mutex_lock(pthread_mutex_t *mutex);

函式解釋:

mutext引數代表通過pthread_mutex_init函式建立的互斥體指標

Mutex解鎖函式

int pthread_mutex_unlock(pthread_mutex_t *mutex);

函式解釋:

mutext引數代表通過pthread_mutex_init函式建立的互斥體指標

Mutext銷燬函式

int pthread_mutex_destroy(pthread_mutex_t *mutex);

函式解釋:

mutext引數代表通過pthread_mutex_init函式建立的互斥體指標

示例程式碼
void * threadFunc(void *arg){

pthread_mutex_t* pthread_mutex=(pthread_mutex_t*)arg;



pthread_mutex_lock(pthread_mutex);



for(int i=0;i<10;i++){

__android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i);

}



pthread_mutex_unlock(pthread_mutex);

return (void *) 0;

}



extern "C"

JNIEXPORT void JNICALL

Java_com_kgdwbb_jnistudy_MainActivity_startNativeThread(JNIEnv* env, jobject thiz,jint count) {

pthread_mutex_t pthread_mutex;

if(pthread_mutex_init(&pthread_mutex,NULL)!=0)

return;



pthread_t pthreads[count];

for(int i=0;i<count;i++){

pthread_create(&pthreads[i],NULL,threadFunc,&pthread_mutex);

}



for(int i=0;i<count;i++){

int retvalue=0;

pthread_join(pthreads[i],(void**)&retvalue);

if(retvalue!=0){

__android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred");

}

}



pthread_mutex_destroy(&pthread_mutex);

}
訊號量Semaphore
標頭檔案

#include <semaphore.h>

函式宣告

Semaphore初始化函式

extern int sem_init(sem_t *sem, int pshared, unsigned int value);

函式解釋:

sem引數代表要建立的Semaphore指標

pshared引數代表要建立的Semaphore的數量

value代表要建立的Semaphore的初始數量

Semaphore獲取函式

extern intsem_wait(sem_t *sem);

函式解釋:

sem引數代表已建立的Semaphore指標

Semaphore釋放函式

extern intsem_post(sem_t *sem);

函式解釋:

sem引數代表已建立的Semaphore指標

Semaphore銷燬函式

extern intsem_destroy(sem_t *sem);

函式解釋:

sem引數代表已建立的Semaphore指標

示例程式碼
void * threadFunc(void *arg){

sem_t* sem=(sem_t*)arg;



sem_wait(sem);



for(int i=0;i<5;i++){

__android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i);

}



sem_post(sem);

return (void *) 0;

}



extern "C"

JNIEXPORT void JNICALL

Java_com_kgdwbb_jnistudy_MainActivity_startNativeThread(JNIEnv* env, jobject thiz,jint count) {

sem_t sem;

if(sem_init(&sem,1,1)!=0)

return;



pthread_t pthreads[count];

for(int i=0;i<count;i++){

pthread_create(&pthreads[i],NULL,threadFunc,&sem);

}



for(int i=0;i<count;i++){

int retvalue=0;

pthread_join(pthreads[i],(void**)&retvalue);

if(retvalue!=0){

__android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred");

}

}



sem_destroy(&sem);

}

結束語

本篇重點介紹了原生執行緒的基礎知識,包括原生執行緒需要用到的函式,原生執行緒的示例程式碼,以及原生程式碼使用Java執行緒進行執行緒同步等相關知識,相信大家學完本篇教程,都能熟練掌握所學的知識點,靈活運用到自己的實際開發中去。