This pthread.h file can create sub-threads in the NDK environment and can control the threads to make mutually exclusive, wait, and destroy.
The reason to write this blog is that I want to write how to play video using FFmpeg, because I need to play audio and video at the same time, so I need to turn on threads and set up the relationship between producer and consumer.
All right, go straight to the whole.
1. Opening and destroying threads
The Pthread_create function can create a thread, the first parameter is a reference to a thread, the second is a thread's property, is generally null, a third is a function that runs on a thread, and a fourth is a parameter that runs a function to a thread
Pthread_create is an open thread, as long as the function thread runs, that is, the function represented by the third parameter is run.
pthread_t pthreads;pthread_create(&pthreads, NULL, threadFunc, (void *) "zzw");
Wait for the thread to complete and return parameters, this if the open thread only one can not write, but if there are multiple threads this must be written, do not write the words will only run the first thread
int retvalue;pthread_join(pthreads,(void**)&retvalue);if(retvalue!=0){ __android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred");}
Let's take a look at the thread run function, which he can get parameters and can end the thread prematurely
void threadfunc (void arg) {
char* str=(char*)arg;for(int i=0;i<3;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d arg = %s",i,str); //线程自杀,需要返回参数 //pthread_exit((void*)2); //线程他杀 //pthread_cancel()}return (void *) 0;
}
Complete example code
#include <jni.h>
#include <string>
#include <android/log.h>
#define LOGE (FORMAT,...) Android_log_print (Android_log_error, "LC XXX", format,##va_args__);
extern "C"
Jniexport jstring
Jnicall
Java_com_example_zth_ndkthread_mainactivity_stringfromjni (
JNIEnv Env,
Jobject/ This */) {
std::string Hello = "Hello from c + +";
Return Env->newstringutf (Hello.c_str ());
}
void threadfunc (void arg) {
char* str=(char*)arg;for(int i=0;i<3;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d arg = %s",i,str); //线程自杀,需要返回参数 //pthread_exit((void*)2); //线程他杀 //pthread_cancel()}return (void *) 0;
}
extern "C"
Jniexport void Jnicall
Java_com_example_zth_ndkthread_mainactivity_startnativethread (jnienv* env, Jobject thiz,jint count) {
pthread_t pthreads;pthread_create(&pthreads, NULL, threadFunc, (void *) "zzw");int retvalue;pthread_join(pthreads,(void**)&retvalue);if(retvalue!=0){ __android_log_print(ANDROID_LOG_ERROR,"hello","thread error occurred");}
}
2. Mutual exclusion Lock
A mutex is the ability to lock a piece of code so that the code cannot be executed again until it is unlocked.
Initialization
pthread_mutex_t pthread_mutex;if(pthread_mutex_init(&pthread_mutex,NULL)!=0) return;
Pass the mutex to the thread run function when the thread is turned on
for(int i=0;i<count;i++){ pthread_create(&pthreads[i],NULL,threadFunc,&pthread_mutex);}
Let's take a look at the thread run function
Remove the mutex and lock it
pthread_mutex_t* pthread_mutex=(pthread_mutex_t*)arg;pthread_mutex_lock(pthread_mutex);
Then a section of code
for(int i=0;i<3;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i);}__android_log_print(ANDROID_LOG_VERBOSE,"hello","————————————");
Unlock
Pthread_mutex_unlock (Pthread_mutex);
Finally destroy the mutex lock
pthread_mutex_destroy(&pthread_mutex);
Run the following effect
03-02 14:25:58.346 10022-10077/com.example.zth.ndkthread v/hello:i = 0
03-02 14:25:58.346 10022-10077/com.example.zth.ndkthread v/hello:i = 1
03-02 14:25:58.346 10022-10077/com.example.zth.ndkthread v/hello:i = 2
03-02 14:25:58.346 10022-10077/com.example.zth.ndkthread V/hello:------------------------
03-02 14:25:58.346 10022-10078/com.example.zth.ndkthread v/hello:i = 0
03-02 14:25:58.346 10022-10078/com.example.zth.ndkthread v/hello:i = 1
03-02 14:25:58.346 10022-10078/com.example.zth.ndkthread v/hello:i = 2
03-02 14:25:58.346 10022-10078/com.example.zth.ndkthread V/hello:------------------------
03-02 14:25:58.347 10022-10079/com.example.zth.ndkthread v/hello:i = 0
03-02 14:25:58.347 10022-10079/com.example.zth.ndkthread v/hello:i = 1
03-02 14:25:58.347 10022-10079/com.example.zth.ndkthread v/hello:i = 2
03-02 14:25:58.347 10022-10079/com.example.zth.ndkthread V/hello: ————————————
What if we don't have a lock?
pthread_mutex_t* pthread_mutex=(pthread_mutex_t*)arg;
Pthread_mutex_lock (Pthread_mutex);
for (int i=0;i<3;i++) {
Android_log_print (android_log_verbose, "Hello", "I =%d", i);
}
Android_log_print (android_log_verbose, "Hello", "------------------------");
Pthread_mutex_unlock (Pthread_mutex);
The results are as follows
03-02 14:36:50.035 13815-13993/com.example.zth.ndkthread v/hello:i = 0
03-02 14:36:50.035 13815-13993/ Com.example.zth.ndkthread v/hello:i = 1
03-02 14:36:50.035 13815-13993/com.example.zth.ndkthread v/hello:i = 2
03-02 14:36:50.035 13815-13993/com.example.zth.ndkthread V/hello:------------------------
03-02 14:36:50.035 13815-13994/com.example.zth.ndkthread v/hello:i = 0
03-02 14:36:50.035 13815-13994/com.example.zth.ndkthread V/ hello:i = 1
03-02 14:36:50.035 13815-13994/com.example.zth.ndkthread v/hello:i = 2
03-02 14:36:50.035 13815-13995 /com.example.zth.ndkthread v/hello:i = 0
03-02 14:36:50.035 13815-13994/com.example.zth.ndkthread V/hello:------- -----------------
03-02 14:36:50.035 13815-13995/com.example.zth.ndkthread v/hello:i = 1
03-02 14:36:50.035 13815-13995/com.example.zth.ndkthread v/hello:i = 2
03-02 14:36:50.035 13815-13995/com.example.zth.ndkthread V/ Hello:------------------------
So a mutex is a thread that is done first, and then another thread.
Example code:
#include <jni.h>
#include <string>
#include <android/log.h>
#include "Pthread.h"
#define LOGE (FORMAT,...) Android_log_print (Android_log_error, "LC XXX", format,##va_args__);
extern "C"
Jniexport jstring
Jnicall
Java_com_example_zth_ndkthread_mainactivity_stringfromjni (
JNIEnv Env,
Jobject/ This */) {
std::string Hello = "Hello from c + +";
Return Env->newstringutf (Hello.c_str ());
}
void threadfunc (void arg) {
pthread_mutex_t* pthread_mutex=(pthread_mutex_t*)arg;pthread_mutex_lock(pthread_mutex);for(int i=0;i<3;i++){ __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",i);}__android_log_print(ANDROID_LOG_VERBOSE,"hello","------------------------");pthread_mutex_unlock(pthread_mutex);return (void *) 0;
}
extern "C"
Jniexport void Jnicall
Java_com_example_zth_ndkthread_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);
}
3. Condition variables
The video decoding is drawn using the producer-consumer model. For example, the products produced by our producers are placed in a queue, and when the producer produces the product, it sends a signal to inform the consumer to consume
This condition variable can wake the thread to run
Initialization
Pthread_cond_init (&c,null);
Turn on the creator thread and the consumer thread
pthread_create(&thread_producer, NULL, produce, (void *) "producer");pthread_create(&thread_comsumer, NULL, comsume, (void *) "comsumer");
Cycle the production of products and then remind consumers
for(;;){ pthread_mutex_lock(&m); productNum++; __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",productNum); pthread_cond_signal(&c); pthread_mutex_unlock(&m);}
Consumer threads wait for a conditional variable reminder if there is no product, and if a product is consumed
pthread_mutex_lock(&m); while(productNum == 0){ pthread_cond_wait(&c,&m); } productNum--; __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",productNum); pthread_mutex_unlock(&m);
Note that the entire process of the generator and the consumer thread is under the mutex, executed in order one by one, so that the calculation of the global variable productnum is not wrong, and one thread executes pthread_cond_signal to trigger another thread to execute
Example code
#include <jni.h>
#include <string>
#include <android/log.h>
#include "Pthread.h"
#define LOGE (FORMAT,...) Android_log_print (Android_log_error, "LC XXX", format,##va_args__);
extern "C"
Jniexport jstring
Jnicall
Java_com_example_zth_ndkthread_mainactivity_stringfromjni (
JNIEnv Env,
Jobject/ This */) {
std::string Hello = "Hello from c + +";
Return Env->newstringutf (Hello.c_str ());
}
int productnum = 0;
pthread_mutex_t m;
pthread_cond_t C;
void produce (void arg) {
char no = (char) arg;
for (;;) {
Pthread_mutex_lock (&M);
productnum++;
__android_log_print (android_log_verbose, "Hello", "I =%d", productnum);
Pthread_cond_signal (&C);
Pthread_mutex_unlock (&M);
}
}
void comsume (void arg) {
char no = (char) arg;
for (;;) {
Pthread_mutex_lock (&M);
while (Productnum = = 0) {
Pthread_cond_wait (&C,&M);
} productNum--; __android_log_print(ANDROID_LOG_VERBOSE,"hello","i = %d",productNum); pthread_mutex_unlock(&m);}
}
extern "C"
Jniexport void Jnicall
Java_com_example_zth_ndkthread_mainactivity_startnativethread (jnienv* env, Jobject thiz,jint count) {
pthread_mutex_init(&m,NULL);pthread_cond_init(&c,NULL);pthread_t thread_producer;pthread_t thread_comsumer;pthread_create(&thread_producer, NULL, produce, (void *) "producer");pthread_create(&thread_comsumer, NULL, comsume, (void *) "comsumer");pthread_join(thread_producer,NULL);pthread_join(thread_comsumer,NULL);pthread_mutex_destroy(&m);pthread_cond_destroy(&c);
}
Reference articles
https://www.jianshu.com/p/453d12c16885
http://blog.csdn.net/lxmhuendan/article/details/11967593
Android NDK Pthreads Detailed use