1.线程和进程的概念
- 线程:进程中的一个实体,是CPU调度和分派的基本单位。可以与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行,线程在运行中呈现间断性。
- 进程:具有一定独立功能的程序关于数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。进程是一个可拥有资源的独立单位,可以独立调度和分派的基本单位。
2. 线程的创建pthread_create()
#include <pthread.h>//需要添加pthread.h头文件
int pthread_create(pthread_t *thread, //指向线程标识符的指针,用pthread_t创建const pthread_attr_t *attr, //设置线程属性,默认为NULLvoid *(*start_rtn)(void *), //线程运行函数的起始地址void *arg //传递给线程函数的参数);
创建一个基本的线程程序如下main.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>void* ptintf_hello_world(void* tid);int main(void){pthread_t thread;int status;int i = 10;printf("Main here. Creating thread %d\n",i);status=pthread_create(&thread, NULL, ptintf_hello_world, &i); pthread_join(thread,NULL); //pthread_join函数以阻塞的方式等待指定的线程结束,如果线程已经结束,函数会立即返回 if(status!=0){printf("pthread_create returned error code %d\n", status);exit(-1);}exit(0);
}
void* ptintf_hello_world(void* tid){printf("Hello world %d.\n", *(int*)tid);exit(0);
}
Android.mk :
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)LOCAL_CFLAGS += -DAWINIC_DEBUG
LOCAL_VENDOR_MODULE := true
LOCAL_LDLIBS := -llogLOCAL_SRC_FILES := main.cpp
LOCAL_MODULE := addValTest
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := falseinclude $(BUILD_EXECUTABLE)
Application.mk:
APP_PLATFORM := android-26
APP_ABI := arm64-v8a, armeabi-v7a
APP_STL := c++_static
创建jni文件夹,然后将main.cpp、Android.mk 、Application.mk三个文件放入jni文件夹下,然后再jni同级目录打开cmd窗口,执行ndk-build,即可生成可执行文件addValTest,然后push到手机system/bin目录下执行:
3. 等待线程结束pthread_join()
先看下面程序:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUMBER_OF_THREADS 10void* ptintf_hello_world(void* tid);
int main(void){pthread_t threads[NUMBER_OF_THREADS];int status = 0;int i = 0;for(i=0; i < NUMBER_OF_THREADS; i++){//循环创建10个线程printf("Main here. Creating thread %d\n",i);//创建线程,线程函数传入参数为istatus = pthread_create(&threads[i], NULL,ptintf_hello_world, &i);if(status != 0){//线程创建不成功,打印错误信息printf("pthread_create returned error code %d\n", status);exit(-1);}}exit(0);
}
void* ptintf_hello_world(void* tid){printf("Hello world %d.\n", *(int*)tid);//在线程函数中打印函数的参数pthread_exit(0);
}
运行结果:
由于我们没有在主线程中等待我们创建出来的10个线程执行完毕,所以创建出来的子线程可能还没来得及执行,就因为主线程(main函数)执行完毕而终止整个进程,导致子线程没法运行。因此printf得到的“Hello world”不是10个,其数量是无法预知的,其顺序也是无法预知的。而且传的是地址,子线程在执行时,i值可能还没更新,所以可能会打印重复的值。
此时我们就需要pthread_join()函数来等待线程执行完成。
pthread_join()函数的原型如下:
int pthread_join(pthread_t thread, //线程标识符,即线程ID,标识唯一线程void **retval); //用户定义的指针,用来存储被等待线程的返回值。
//返回值:0:成功;其他:失败的错误号
使用pthread_join()函数之后的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUMBER_OF_THREADS 10void* ptintf_hello_world(void* tid);
int main(void){pthread_t threads[NUMBER_OF_THREADS];int status = 0;int i = 0;for(i=0; i < NUMBER_OF_THREADS; i++){//循环创建10个现场printf("Main here. Creating thread %d\n",i);//创建线程,线程函数传入参数为istatus=pthread_create(&threads[i], NULL, ptintf_hello_world, &i);if(status != 0){//线程创建不成功,打印错误信息printf("pthread_create returned error code %d\n", status);exit(-1);}}for(i=0; i < NUMBER_OF_THREADS; i++){pthread_join(threads[i], NULL);}exit(0);
}
void* ptintf_hello_world(void* tid){printf("Hello world %d.\n", *(int*)tid);//在线程函数中打印函数的参数pthread_exit(0);
}
可以看出,此时所有子线程都执行完毕,打印了10个。但是线程执行的顺序是不固定的,也就是说我们无法预知打印的顺序。根据代码判断程序的输出是不可行的,我们只知道输出的内容,但不知道输出的顺序。
除非我们在每个子线程创建之后,一直等其运行结束,然后才开始创建下一个子线程。即将pthread_join()函数放到紧挨着pthread_create()函数的后面,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUMBER_OF_THREADS 10void* ptintf_hello_world(void* tid);
int main(void){pthread_t threads[NUMBER_OF_THREADS];int status = 0;int i = 0;for(i=0; i < NUMBER_OF_THREADS; i++){//循环创建10个现场printf("Main here. Creating thread %d\n",i);//创建线程,线程函数传入参数为istatus=pthread_create(&threads[i], NULL, ptintf_hello_world, &i);pthread_join(threads[i], NULL);if(status!=0){//线程创建不成功,打印错误信息printf("pthread_create returned error code %d\n",status);exit(-1);}}exit(0);
}
void* ptintf_hello_world(void* tid){printf("Hello world %d.\n", *(int*)tid);//在线程函数中打印函数的参数pthread_exit(0);
}
运行结果如下:
4. 使用pthread_join()得到线程函数的返回值
使用pthread_join()除了有阻塞线程功能之外,还可以利用其第二个参数,得到线程函数的返回值。代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUMBER_OF_THREADS 10void* ptintf_hello_world(void* tid);
int main(void){pthread_t threads[NUMBER_OF_THREADS];int status = 0;int i = 0;for(i=0; i<NUMBER_OF_THREADS; i++){printf("Main here. Creating thread %d\n",i);status = pthread_create(&threads[i], NULL, ptintf_hello_world, &i);//使用res得到线程函数的返回值 int** res=(int**)malloc(sizeof(int*));pthread_join(threads[i],(void**)res); //pthread_join函数以阻塞的方式等待指定的线程结束printf("res[%d]:%d\n",i,**res);//打印线程函数的返回值 free(*res); //释放线程处理函数中使用malloc分配的内存空间 if(status!=0){printf("pthread_create returned error code %d\n",status);exit(-1);}}exit(0);
}
void* ptintf_hello_world(void* tid){int val = *(int*)tid;printf("Hello world %d.\n", val);int* a=(int*)malloc(sizeof(int));*a= val * val;return a; //线程函数的返回值
}
运行结果如下:
参考链接: C语言——多线程基础(pthread)