前言
为了帮助同学们完成痛苦的实验课程设计,本作者将其作出的实验结果及代码贴至CSDN中,供同学们学习参考。如有不足或描述不完善之处,敬请各位指出,欢迎各位的斧正!
一、实验目的
- 理解Linux的线程原理。
- 掌握和使用线程函数实现线程的操作。
- 掌握和使用互斥锁和信号量实现线程同步。
- 掌握线程池。
二、实验工具与设备
装有Linux系统的计算机
三、实验预备知识
线程可以提高应用程序在多核环境下处理诸如文件I/O或者socket I/O等会产生堵塞的情况的表现性能。在Unix系统中,一个进程包含很多东西,包括可执行程序以及一大堆的诸如文件描述符地址空间等资源。在很多情况下,完成相关任务的不同代码间需要交换数据。如果采用多进程的方式,那么通信就需要在用户空间和内核空间进行频繁的切换,开销很大。但是如果使用多线程的方式,因为可以使用共享的全局变量,所以线程间的通信(数据交换)变得非常高效。
头文件:#include <pthread.h>
需要的编译条件:-pthread
线程结构体pthread_attr_t中记录线程的信息。
typedef struct
{
int detachstate; 线程的分离状态
int schedpolicy; 线程调度策略
structsched_param schedparam; 线程的调度参数
int inheritsched; 线程的继承性
int scope; 线程的作用域
size_t guardsize; 线程栈末尾的警戒缓冲区大小
int stackaddr_set;
void* stackaddr; 线程栈的位置
size_t stacksize; 线程栈的大小
}pthread_attr_t;
线程相关的接口函数:
对线程属性初始化/去除初始化
int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr);
创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
向线程发送终止信号
int pthread_cancel(pthread_t thread);
使线程进入分离态
int pthread_detach(pthread_t thread);
比较两个线程的标识符
int pthread_equal(pthread_t t1, pthread_t t2);
使线程退出
void pthread_exit(void *retval);
通过结构体初始化,用于明确指定线程属性
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
等待指定线程的结束
int pthread_join(pthread_t thread, void **retval);
返回线程当前的描述符
pthread_t pthread_self(void);
四、实验内容和步骤
- 创建线程。
#include <stdio.h>
#include <pthread.h>
void *mythread1(void)
{
int i;
for(i = 0; i < 10; i++)
{
printf("This is the pthread1,i=%d\n",i);
sleep(1);
}
}
void *mythread2(void)
{
int i;
for(i = 0; i < 10; i++)
{
printf("This is the pthread1,i=%d\n",i );
sleep(1);
}
}
int main(int argc, const char *argv[])
{
int i = 0;
int ret = 0;
pthread_t id1,id2;
ret = pthread_create(&id1, NULL, (void *)mythread1,NULL);
if(ret)
{
printf("Create pthread error!\n");
return 1;
}
ret = pthread_create(&id2, NULL, (void *)mythread2,NULL);
if(ret)
{
printf("Create pthread error!\n");
return 1;
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
return 0;
}
执行以下命令编译程序并执行:gcc -o Createthread Createthread.c -lpthread
- 创建两个线程实现对一个数的递加。
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 20
pthread_t thread[2]; //两个线程
pthread_mutex_t mut;
int number=0;
int i;
void *thread1()
{
printf ("thread1 : this is the thread1\n");
for (i = 0; i < MAX; i++) //模拟线程执行时间
{
printf("thread1 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}
printf("thread1 :主函数在等我完成任务吗?\n");
pthread_exit(NULL);
}
void *thread2()
{
printf(""thread2 : this is the thread2\n");
for (i = 0; i < MAX; i++)
{
printf("thread2 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}
printf("thread2 :主函数在等我完成任务吗?\n");
pthread_exit(NULL);
}
void thread_create(void) //创建两个线程
{
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*创建线程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("线程1创建失败\n");
else
printf("线程1被创建\n");
if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("线程2创建失败\n");
else
printf("线程2被创建\n");
}
void thread_wait(void)
{
/*等待线程结束*/
if(thread[0] !=0)
{ //comment4
pthread_join(thread[0],NULL);
printf("线程1已经结束\n");
}
if(thread[1] !=0)
{
//comment5
pthread_join(thread[1],NULL);
printf("线程2已经结束\n");
}
}
int main()
{
/*用默认属性初始化互斥锁*/
pthread_mutex_init(&mut,NULL);
printf("创建线程\n");
thread_create();
printf("等待线程完成任务\n");
thread_wait();
return 0;
}
通过以下命令编译:gcc -lpthread -o thread_example thread_example.c
- 线程同步
未同步示例程序:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#define LEN 100000
int num = 0;
void* thread_func(void* arg) {
for (int i = 0; i< LEN; ++i) {
num += 1;
}
return NULL;
}
int main() {
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, (void*)thread_func, NULL);
pthread_create(&tid2, NULL, (void*)thread_func, NULL);
char* rev = NULL;
pthread_join(tid1, (void *)&rev);
pthread_join(tid2, (void *)&rev);
printf("correct result=%d, wrong result=%d.\n", 2*LEN, num);
return 0;
}
运行结果:correct result=200000, wrong result=106860.
通过互斥解决同步问题的程序:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#define LEN 100000
int num = 0;
void* thread_func(void* arg) {
pthread_mutex_t* p_mutex = (pthread_mutex_t*)arg;
for (int i = 0; i< LEN; ++i) {
pthread_mutex_lock(p_mutex);
num += 1;
pthread_mutex_unlock(p_mutex);
}
return NULL;
}
int main() {
pthread_mutex_t m_mutex;
pthread_mutex_init(&m_mutex, NULL);
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, (void*)thread_func, (void*)&m_mutex);
pthread_create(&tid2, NULL, (void*)thread_func, (void*)&m_mutex);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&m_mutex);
printf("correct result=%d, result=%d.\n", 2*LEN, num);
return 0;
}
运行结果:correct result=200000, result=200000.
- 编写信号量使用程序
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
#include<errno.h>
#include<string.h>
#include<semaphore.h>
#define NUM 5
int queue[NUM];
sem_t psem, csem;
void producer(void* arg) {
int pos = 0;
int num, count = 0;
for (int i=0; i<12; ++i) {
num = rand() % 100;
count += num;
sem_wait(&psem);
queue[pos] = num;
sem_post(&csem);
printf("producer: %d\n", num);
pos = (pos+1) % NUM;
sleep(rand()%2);
}
printf("producer count=%d\n", count);
}
void consumer(void* arg){
int pos = 0;
int num, count = 0;
for (int i=0; i<12; ++i) {
sem_wait(&csem);
num = queue[pos];
sem_post(&psem);
printf("consumer: %d\n", num);
count += num;
pos = (pos+1) % NUM;
sleep(rand()%3);
}
printf("consumer count=%d\n", count);
}
int main() {
sem_init(&psem, 0, NUM);
sem_init(&csem, 0, 0);
pthread_t tid[2];
pthread_create(&tid[0], NULL, (void*)producer, NULL);
pthread_create(&tid[1], NULL, (void*)consumer, NULL);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
sem_destroy(&psem);
sem_destroy(&csem);
return 0;
}
- 编写线程池程序
1.理解并运行以下线程实现
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
typedef struct condition
{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
}condition_t;
typedef struct task
{
void *(*run)(void *arg);
void *arg;
struct task *next;
}task_t;
typedef struct threadpool
{
condition_t ready;
task_t *first;
task_t *last;
int counter;
int idle;
int max_threads;
int quit;
}threadpool_t;
int condition_init(condition_t *cond)
{
int status;
if((status = pthread_mutex_init(&cond->pmutex,NULL)))//返回0代表初始化成功
return status;
if((status = pthread_cond_init(&cond->pcond,NULL)))
return status;
return 0;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond -> pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond -> pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond -> pcond,&cond -> pmutex);
}
int condition_timewait(condition_t *cond,const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);
}
int condition_signal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond -> pcond);
}
int condition_destory(condition_t *cond)
{
int status;
if((status = pthread_mutex_destroy(&cond -> pmutex)))
return status;
if((status = pthread_cond_destroy(&cond -> pcond)))
return status;
return 0;
}
void *thread_routine(void *arg)
{
struct timespec abstime;
int timeout;
printf("thread 0x%0x is starting\n",(int)pthread_self());
threadpool_t *pool = (threadpool_t *)arg;
while(1)
{
timeout = 0;
condition_lock(&pool -> ready);
pool -> idle++;
//等待队列有任务到来或者线程池销毁的通知
while(pool -> first == NULL && !pool -> quit)
{
printf("thread 0x%0x is waiting\n",(int)pthread_self());
clock_gettime(CLOCK_REALTIME,&abstime);
abstime.tv_sec += 2;
int status=condition_timewait(&pool -> ready,&abstime);
if(status == ETIMEDOUT)
{
printf("thread 0x%0x is wait timed out\n",(int)pthread_self());
timeout = 1;
break;
}
}
//等到到条件,处于工作状态
pool -> idle--;
if(pool -> first != NULL)
{
task_t *t = pool -> first;
pool -> first = t -> next;
//需要先解锁,以便添加新任务。其他消费者线程能够进入等待任务。
condition_unlock(&pool -> ready);
t -> run(t->arg);
free(t);
condition_lock(&pool -> ready);
}
//等待线程池销毁的通知
if(pool -> quit && pool ->first == NULL)
{
pool -> counter--;
if(pool->counter == 0)
{
condition_signal(&pool -> ready);
}
condition_unlock(&pool->ready);
//跳出循环之前要记得解锁
break;
}
if(timeout &&pool -> first ==NULL)
{
pool -> counter--;
condition_unlock(&pool->ready);
//跳出循环之前要记得解锁
break;
}
condition_unlock(&pool -> ready);
}
printf("thread 0x%0x is exiting\n",(int)pthread_self());
return NULL;
}
//初始化
void threadpool_init(threadpool_t *pool, int threads)
{
condition_init(&pool -> ready);
pool -> first = NULL;
pool -> last = NULL;
pool -> counter = 0;
pool -> idle = 0;
pool -> max_threads = threads;
pool -> quit = 0;
}
//加任务
void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg),void *arg)
{
task_t *newstask = (task_t *)malloc(sizeof(task_t));
newstask->run = run;
newstask->arg = arg;
newstask -> next = NULL;
condition_lock(&pool -> ready);
//将任务添加到对列中
if(pool -> first ==NULL)
{
pool -> first = newstask;
}
else
pool -> last -> next = newstask;
pool -> last = newstask;
//如果有等待线程,则唤醒其中一个
if(pool -> idle > 0)
{
condition_signal(&pool -> ready);
}
else if(pool -> counter < pool -> max_threads)
{
pthread_t tid;
pthread_create(&tid,NULL,thread_routine,pool);
pool -> counter++;
}
condition_unlock(&pool -> ready);
}
//销毁线程池
void threadpool_destory(threadpool_t *pool)
{
if(pool -> quit)
{
return;
}
condition_lock(&pool -> ready);
pool->quit = 1;
if(pool -> counter > 0)
{
if(pool -> idle > 0)
condition_broadcast(&pool->ready);
while(pool -> counter > 0)
{
condition_wait(&pool->ready);
}
}
condition_unlock(&pool->ready);
condition_destory(&pool -> ready);
}
void *mytask(void *arg)
{
printf("thread 0x%0x is working on task %d\n",(int)pthread_self(),*(int*)arg);
sleep(1);
free(arg);
return NULL;
}
int main()
{
threadpool_t pool;
threadpool_init(&pool,3);
int i ;
for(i = 0; i < 10; i++)
{
int *arg = (int *)malloc(sizeof(int));
*arg = i;
threadpool_add_task(&pool,mytask,arg);
}
sleep(15);
threadpool_destory(&pool);
return 0;
}
编译运行:gcc Threadpool.c -o Threadpool -lpthread -lrt
2.参考https://www.cnblogs.com/jiangzhaowei/p/10383049.html编写复杂的线程池;
3.改造属于自己的线程池代码。
五、实验代码及步骤截图
3-1.c:
#include <stdio.h>
#include <pthread.h>
void *mythread1(void)
{
int i;
for(i = 0; i < 10; i++)
{
printf("This is the pthread1,i=%d\n",i);
sleep(1);
}
}
void *mythread2(void)
{
int i;
for(i = 0; i < 10; i++)
{
printf("This is the pthread2,i=%d\n",i );
sleep(1);
}
}
int main(int argc, const char *argv[])
{
int i = 0;
int ret = 0;
pthread_t id1,id2;
ret = pthread_create(&id1, NULL, (void *)mythread1,NULL);
if(ret)
{
printf("Create pthread error!\n");
return 1;
}
ret = pthread_create(&id2, NULL, (void *)mythread2,NULL);
if(ret)
{
printf("Create pthread error!\n");
return 1;
}
pthread_join(id1,NULL);
pthread_join(id2,NULL);
return 0;
}
实验3-1运行截图如下:
3-2.c:
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 20
pthread_t thread[2]; //两个线程
pthread_mutex_t mut;
int number=0;
int i;
void *thread1()
{
printf ("thread1 : this is the thread1\n");
for (i = 0; i < MAX; i++) //模拟线程执行时间
{
printf("thread1 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}
printf("thread1 :主函数在等我完成任务吗?\n");
pthread_exit(NULL);
}
void *thread2()
{
printf("thread2 : this is the thread2\n");
for (i = 0; i < MAX; i++)
{
printf("thread2 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}
printf("thread2 :主函数在等我完成任务吗?\n");
pthread_exit(NULL);
}
void thread_create(void) //创建两个线程
{
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*创建线程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("线程1创建失败\n");
else
printf("线程1被创建\n");
if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("线程2创建失败\n");
else
printf("线程2被创建\n");
}
void thread_wait(void)
{
/*等待线程结束*/
if(thread[0] !=0)
{ //comment4
pthread_join(thread[0],NULL);
printf("线程1已经结束\n");
}
if(thread[1] !=0)
{
//comment5
pthread_join(thread[1],NULL);
printf("线程2已经结束\n");
}
}
int main()
{
/*用默认属性初始化互斥锁*/
pthread_mutex_init(&mut,NULL);
printf("创建线程\n");
thread_create();
printf("等待线程完成任务\n");
thread_wait();
return 0;
}
实验3-2运行截图如下:
3-3.c:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#define LEN 100000
int num = 0;
void* thread_func(void* arg)
{
int i;
for (i=0; i<LEN; ++i)
{
num += 1;
}
return NULL;
}
int main()
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, (void*)thread_func, NULL);
pthread_create(&tid2, NULL, (void*)thread_func, NULL);
char* rev = NULL;
pthread_join(tid1, (void *)&rev);
pthread_join(tid2, (void *)&rev);
printf("correct result=%d, wrong result=%d.\n", 2*LEN, num);
return 0;
}
3-3.c运行截图如下:
3-3-1.c:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#define LEN 100000
int num = 0;
void* thread_func(void* arg)
{
pthread_mutex_t* p_mutex = (pthread_mutex_t*)arg;
int i;
for (i = 0; i< LEN; ++i)
{
pthread_mutex_lock(p_mutex);
num += 1;
pthread_mutex_unlock(p_mutex);
}
return NULL;
}
int main()
{
pthread_mutex_t m_mutex;
pthread_mutex_init(&m_mutex, NULL);
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, (void*)thread_func, (void*)&m_mutex);
pthread_create(&tid2, NULL, (void*)thread_func, (void*)&m_mutex);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pthread_mutex_destroy(&m_mutex);
printf("correct result=%d, result=%d.\n", 2*LEN, num);
return 0;
}
3-3-1.c运行截图如下:
3-4.c:
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<pthread.h>
#include<errno.h>
#include<string.h>
#include<semaphore.h>
#define NUM 5
int queue[NUM];
sem_t psem, csem;
void producer(void* arg) {
int pos = 0;
int num, count = 0;
int i;
for (i=0; i<12; ++i) {
num = rand() % 100;
count += num;
sem_wait(&psem);
queue[pos] = num;
sem_post(&csem);
printf("producer: %d\n", num);
pos = (pos+1) % NUM;
sleep(rand()%2);
}
printf("producer count=%d\n", count);
}
void consumer(void* arg){
int pos = 0;
int num, count = 0;
int i;
for (i=0; i<12; ++i) {
sem_wait(&csem);
num = queue[pos];
sem_post(&psem);
printf("consumer: %d\n", num);
count += num;
pos = (pos+1) % NUM;
sleep(rand()%3);
}
printf("consumer count=%d\n", count);
}
int main() {
sem_init(&psem, 0, NUM);
sem_init(&csem, 0, 0);
pthread_t tid[2];
pthread_create(&tid[0], NULL, (void*)producer, NULL);
pthread_create(&tid[1], NULL, (void*)consumer, NULL);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
sem_destroy(&psem);
sem_destroy(&csem);
return 0;
}
3-4.c运行截图如下:
3-5.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <pthread.h>
typedef struct condition
{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
}condition_t;
typedef struct task
{
void *(*run)(void *arg);
void *arg;
struct task *next;
}task_t;
typedef struct threadpool
{
condition_t ready;
task_t *first;
task_t *last;
int counter;
int idle;
int max_threads;
int quit;
}threadpool_t;
int condition_init(condition_t *cond)
{
int status;
if((status = pthread_mutex_init(&cond->pmutex,NULL)))//返回0代表初始化成功
return status;
if((status = pthread_cond_init(&cond->pcond,NULL)))
return status;
return 0;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond -> pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond -> pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond -> pcond,&cond -> pmutex);
}
int condition_timewait(condition_t *cond,const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);
}
int condition_signal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond -> pcond);
}
int condition_destory(condition_t *cond)
{
int status;
if((status = pthread_mutex_destroy(&cond -> pmutex)))
return status;
if((status = pthread_cond_destroy(&cond -> pcond)))
return status;
return 0;
}
void *thread_routine(void *arg)
{
struct timespec abstime;
int timeout;
printf("thread 0x%0x is starting\n",(int)pthread_self());
threadpool_t *pool = (threadpool_t *)arg;
while(1)
{
timeout = 0;
condition_lock(&pool -> ready);
pool -> idle++;
//等待队列有任务到来或者线程池销毁的通知
while(pool -> first == NULL && !pool -> quit)
{
printf("thread 0x%0x is waiting\n",(int)pthread_self());
clock_gettime(CLOCK_REALTIME,&abstime);
abstime.tv_sec += 2;
int status=condition_timewait(&pool -> ready,&abstime);
if(status == ETIMEDOUT)
{
printf("thread 0x%0x is wait timed out\n",(int)pthread_self());
timeout = 1;
break;
}
}
//等到到条件,处于工作状态
pool -> idle--;
if(pool -> first != NULL)
{
task_t *t = pool -> first;
pool -> first = t -> next;
//需要先解锁,以便添加新任务。其他消费者线程能够进入等待任务。
condition_unlock(&pool -> ready);
t -> run(t->arg);
free(t);
condition_lock(&pool -> ready);
}
//等待线程池销毁的通知
if(pool -> quit && pool ->first == NULL)
{
pool -> counter--;
if(pool->counter == 0)
{
condition_signal(&pool -> ready);
}
condition_unlock(&pool->ready);
//跳出循环之前要记得解锁
break;
}
if(timeout &&pool -> first ==NULL)
{
pool -> counter--;
condition_unlock(&pool->ready);
//跳出循环之前要记得解锁
break;
}
condition_unlock(&pool -> ready);
}
printf("thread 0x%0x is exiting\n",(int)pthread_self());
return NULL;
}
//初始化
void threadpool_init(threadpool_t *pool, int threads)
{
condition_init(&pool -> ready);
pool -> first = NULL;
pool -> last = NULL;
pool -> counter = 0;
pool -> idle = 0;
pool -> max_threads = threads;
pool -> quit = 0;
}
//加任务
void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg),void *arg)
{
task_t *newstask = (task_t *)malloc(sizeof(task_t));
newstask->run = run;
newstask->arg = arg;
newstask -> next = NULL;
condition_lock(&pool -> ready);
//将任务添加到对列中
if(pool -> first ==NULL)
{
pool -> first = newstask;
}
else
pool -> last -> next = newstask;
pool -> last = newstask;
//如果有等待线程,则唤醒其中一个
if(pool -> idle > 0)
{
condition_signal(&pool -> ready);
}
else if(pool -> counter < pool -> max_threads)
{
pthread_t tid;
pthread_create(&tid,NULL,thread_routine,pool);
pool -> counter++;
}
condition_unlock(&pool -> ready);
}
//销毁线程池
void threadpool_destory(threadpool_t *pool)
{
if(pool -> quit)
{
return;
}
condition_lock(&pool -> ready);
pool->quit = 1;
if(pool -> counter > 0)
{
if(pool -> idle > 0)
condition_broadcast(&pool->ready);
while(pool -> counter > 0)
{
condition_wait(&pool->ready);
}
}
condition_unlock(&pool->ready);
condition_destory(&pool -> ready);
}
void *mytask(void *arg)
{
printf("thread 0x%0x is working on task %d\n",(int)pthread_self(),*(int*)arg);
sleep(1);
free(arg);
return NULL;
}
int main()
{
threadpool_t pool;
threadpool_init(&pool,3);
int i ;
for(i = 0; i < 10; i++)
{
int *arg = (int *)malloc(sizeof(int));
*arg = i;
threadpool_add_task(&pool,mytask,arg);
}
sleep(15);
threadpool_destory(&pool);
return 0;
}
3-5.c运行截图如下:
2.参考https://www.cnblogs.com/jiangzhaowei/p/10383049.html编写复杂的线程池;
Main.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <string.h>
#include "lib_thread_pool.h"
static void* thread_1(void* arg);
static void* thread_2(void* arg);
static void* thread_3(void* arg);
static void DisplayPoolStatus(CThread_pool_t* pPool);
int nKillThread = 0;
int main()
{
CThread_pool_t* pThreadPool = NULL;
pThreadPool = ThreadPoolConstruct(2, 1);
int nNumInput = 5;
char LogInput[] = "OK!";
DisplayPoolStatus(pThreadPool);
/*可用AddWorkLimit()替换看执行的效果*/
pThreadPool->AddWorkUnlimit((void*)pThreadPool, thread_1, (void*)NULL);
/*
* 没加延迟发现连续投递任务时pthread_cond_wait()会收不到信号pthread_cond_signal() !!
* 因为AddWorkUnlimit()进去后调用pthread_mutex_lock()把互斥锁锁上,导致pthread_cond_wait()
* 收不到信号!!也可在AddWorkUnlimit()里面加个延迟,一般情况可能也遇不到这个问题
*/
usleep(10);
pThreadPool->AddWorkUnlimit((void*)pThreadPool, thread_2, (void*)nNumInput);
usleep(10);
pThreadPool->AddWorkUnlimit((void*)pThreadPool, thread_3, (void*)LogInput);
usleep(10);
DisplayPoolStatus(pThreadPool);
nKillThread = 1;
usleep(100); /**< 先让线程退出 */
DisplayPoolStatus(pThreadPool);
nKillThread = 2;
usleep(100);
DisplayPoolStatus(pThreadPool);
nKillThread = 3;
usleep(100);
DisplayPoolStatus(pThreadPool);
pThreadPool->Destruct((void*)pThreadPool);
return 0;
}
static void* thread_1(void* arg)
{
printf("Thread 1 is running !\n");
while(nKillThread != 1)
usleep(10);
return NULL;
}
static void* thread_2(void* arg)
{
int nNum = (int)arg;
printf("Thread 2 is running !\n");
printf("Get Number %d\n", nNum);
while(nKillThread != 2)
usleep(10);
return NULL;
}
static void* thread_3(void* arg)
{
char *pLog = (char*)arg;
printf("Thread 3 is running !\n");
printf("Get String %s\n", pLog);
while(nKillThread != 3)
usleep(10);
return NULL;
}
static void DisplayPoolStatus(CThread_pool_t* pPool)
{
static int nCount = 1;
printf("******************\n");
printf("nCount = %d\n", nCount++);
printf("max_thread_num = %d\n", pPool->GetMaxThreadNum((void*)pPool));
printf("current_pthread_num = %d\n", pPool->GetCurThreadNum((void*)pPool));
printf("current_pthread_task_num = %d\n", pPool->GetCurTaskThreadNum((void*)pPool));
printf("cur_queue_size = %d\n", pPool->GetCurTaskNum((void*)pPool));
printf("******************\n");
}
Lib_thread_pool.c:
/************************************************************************
* module : 线程池实现
* file name : lib_thread_pool.c
* Author :
* version : V1.0
* DATE :
* directory :
* description :
* related document:
*
************************************************************************/
/*-----------------------includes-------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <string.h>
#include "lib_thread_pool.h"
/*---------------constants/macro definition---------------------*/
/*---------------global variables definition-----------------------*/
/*---------------functions declaration--------------------------*/
static void * ThreadPoolRoutine (void *arg);
/*---------------functions definition---------------------------*/
/****************************************************************
* function name : ThreadPoolAddWorkLimit
* functional description : 向线程池投递任务,无空闲线程则阻塞
* input parameter : pthis 线程池指针
process 回调函数
arg 回调函数的参数
* output parameter :
* return value : 0 - 成功;-1 - 失败
* history :
*****************************************************************/
static int ThreadPoolAddWorkLimit(void* pthis,void *(*process) (void *arg), void *arg)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
worker_t *newworker = (worker_t *) malloc (sizeof (worker_t));
if (NULL == newworker)
{
return -1;
}
newworker->process = process; /**< 回调函数,在线程ThreadPoolRoutine()中执行 */
newworker->arg = arg; /**< 回调函数参数 */
newworker->next = NULL;
pthread_mutex_lock(&(pool->queue_lock));
worker_t *member = pool->queue_head; /**< 等待队列任务链表 */
if (member != NULL)
{
while (member->next != NULL)
{
member = member->next;
}
member->next = newworker; /**< 放入链表尾 */
}
else
{
pool->queue_head = newworker; /**< 放入链表头 */
}
assert (pool->queue_head != NULL);
pool->cur_queue_size++; /**< 等待队列加1 */
int FreeThreadNum = pool->current_pthread_num - pool->current_pthread_task_num;
if((0 == FreeThreadNum) && (pool->current_pthread_num < pool->max_thread_num))
{/**< 如果没有空闲线程且池中当前线程数不超过可容纳最大线程 */
int current_pthread_num = pool->current_pthread_num;
pool->threadid = (pthread_t *) realloc(pool->threadid,(current_pthread_num + 1) * sizeof (pthread_t)); /**< 新增线程 */
pthread_create (&(pool->threadid[current_pthread_num]), NULL, ThreadPoolRoutine, (void*)pool);
pool->current_pthread_num++; /**< 当前池中线程总数加1 */
pool->current_pthread_task_num++; /**< 分配任务的线程数加1 */
pthread_mutex_unlock (&(pool->queue_lock));
pthread_cond_signal (&(pool->queue_ready)); /**< 发送信号给1个处于条件阻塞等待状态的线程 */
return 0;
}
pool->current_pthread_task_num++;
pthread_mutex_unlock(&(pool->queue_lock));
pthread_cond_signal(&(pool->queue_ready));
// usleep(10); //看情况加
return 0;
}
/****************************************************************
* function name : ThreadPoolAddWorkUnlimit
* functional description : 向线程池投递任务
* input parameter : pthis 线程池指针
process 回调函数
arg 回调函数的参数
* output parameter :
* return value : 0 - 成功;-1 - 失败
* history :
*****************************************************************/
static int ThreadPoolAddWorkUnlimit(void* pthis,void *(*process) (void *arg), void *arg)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
worker_t *newworker = (worker_t *) malloc (sizeof (worker_t));
if (NULL == newworker)
{
return -1;
}
newworker->process = process;
newworker->arg = arg;
newworker->next = NULL;
pthread_mutex_lock(&(pool->queue_lock));
worker_t *member = pool->queue_head;
if (member != NULL)
{
while (member->next != NULL)
{
member = member->next;
}
member->next = newworker;
}
else
{
pool->queue_head = newworker;
}
assert (pool->queue_head != NULL);
pool->cur_queue_size++;
int FreeThreadNum = pool->current_pthread_num - pool->current_pthread_task_num;
if(0 == FreeThreadNum) /**< 只判断是否没有空闲线程 */
{
int current_pthread_num = pool->current_pthread_num;
pool->threadid = (pthread_t *) realloc(pool->threadid,(current_pthread_num + 1) * sizeof (pthread_t));
pthread_create (&(pool->threadid[current_pthread_num]), NULL, ThreadPoolRoutine, (void*)pool);
pool->current_pthread_num++;
if (pool->current_pthread_num > pool->max_thread_num)
{
pool->max_thread_num = pool->current_pthread_num;
}
pool->current_pthread_task_num++;
pthread_mutex_unlock (&(pool->queue_lock));
pthread_cond_signal (&(pool->queue_ready));
return 0;
}
pool->current_pthread_task_num++;
pthread_mutex_unlock(&(pool->queue_lock));
pthread_cond_signal(&(pool->queue_ready));
// usleep(10); //看情况加
return 0;
}
/****************************************************************
* function name : ThreadPoolGetThreadMaxNum
* functional description : 获取线程池可容纳的最大线程数
* input parameter : pthis 线程池指针
* output parameter :
* return value : 线程池可容纳的最大线程数
* history :
*****************************************************************/
static int ThreadPoolGetThreadMaxNum(void* pthis)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
pthread_mutex_lock(&(pool->queue_lock));
int num = pool->max_thread_num;
pthread_mutex_unlock(&(pool->queue_lock));
return num;
}
/****************************************************************
* function name : ThreadPoolGetCurrentThreadNum
* functional description : 获取线程池存放的线程数
* input parameter : pthis 线程池指针
* output parameter :
* return value : 线程池存放的线程数
* history :
*****************************************************************/
static int ThreadPoolGetCurrentThreadNum(void* pthis)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
pthread_mutex_lock(&(pool->queue_lock));
int num = pool->current_pthread_num;
pthread_mutex_unlock(&(pool->queue_lock));
return num;
}
/****************************************************************
* function name : ThreadPoolGetCurrentTaskThreadNum
* functional description : 获取当前正在执行任务和已分配任务的线程数目和
* input parameter : pthis 线程池指针
* output parameter :
* return value : 当前正在执行任务和已分配任务的线程数目和
* history :
*****************************************************************/
static int ThreadPoolGetCurrentTaskThreadNum(void* pthis)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
pthread_mutex_lock(&(pool->queue_lock));
int num = pool->current_pthread_task_num;
pthread_mutex_unlock(&(pool->queue_lock));
return num;
}
/****************************************************************
* function name : ThreadPoolGetCurrentTaskNum
* functional description : 获取线程池等待队列任务数
* input parameter : pthis 线程池指针
* output parameter :
* return value : 等待队列任务数
* history :
*****************************************************************/
static int ThreadPoolGetCurrentTaskNum(void* pthis)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
pthread_mutex_lock(&(pool->queue_lock));
int num = pool->cur_queue_size;
pthread_mutex_unlock(&(pool->queue_lock));
return num;
}
/****************************************************************
* function name : ThreadPoolDestroy
* functional description : 销毁线程池
* input parameter : pthis 线程池指针
* output parameter :
* return value : 0 - 成功;-1 - 失败
* history :
*****************************************************************/
static int ThreadPoolDestroy (void *pthis)
{
CThread_pool_t *pool = (CThread_pool_t *)pthis;
if (pool->shutdown) /**< 已销毁 */
{
return -1;
}
pool->shutdown = 1; /**< 销毁标志置位 */
pthread_cond_broadcast (&(pool->queue_ready)); /**< 唤醒所有pthread_cond_wait()等待线程 */
int i;
for (i = 0; i < pool->current_pthread_num; i++)
{
pthread_join (pool->threadid[i], NULL); /**< 等待所有线程执行结束 */
}
free (pool->threadid); /**< 释放 */
worker_t *head = NULL;
while (pool->queue_head != NULL)
{
head = pool->queue_head;
pool->queue_head = pool->queue_head->next;
free (head); /**< 释放 */
}
pthread_mutex_destroy(&(pool->queue_lock)); /**< 销毁 */
pthread_cond_destroy(&(pool->queue_ready)); /**< 销毁 */
free (pool); /**< 释放 */
pool=NULL;
return 0;
}
/****************************************************************
* function name : ThreadPoolRoutine
* functional description : 线程池中运行的线程
* input parameter : arg 线程池指针
* output parameter :
* return value : NULL
* history :
*****************************************************************/
static void * ThreadPoolRoutine (void *arg)
{
CThread_pool_t *pool = (CThread_pool_t *)arg;
while (1)
{
pthread_mutex_lock (&(pool->queue_lock)); /**< 上锁, pthread_cond_wait()调用会解锁*/
while ((pool->cur_queue_size == 0) && (!pool->shutdown)) /**< 队列没有等待任务*/
{
pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock)); /**< 条件锁阻塞等待条件信号*/
}
if (pool->shutdown)
{
pthread_mutex_unlock (&(pool->queue_lock));
pthread_exit (NULL); /**< 释放线程 */
}
assert (pool->cur_queue_size != 0);
assert (pool->queue_head != NULL);
pool->cur_queue_size--; /**< 等待任务减1,准备执行任务*/
worker_t *worker = pool->queue_head; /**< 取等待队列任务结点头*/
pool->queue_head = worker->next; /**< 链表后移 */
pthread_mutex_unlock (&(pool->queue_lock));
(*(worker->process)) (worker->arg); /**< 执行回调函数 */
pthread_mutex_lock (&(pool->queue_lock));
pool->current_pthread_task_num--; /**< 函数执行结束 */
free (worker); /**< 释放任务结点 */
worker = NULL;
if ((pool->current_pthread_num - pool->current_pthread_task_num) > pool->free_pthread_num)
{
pthread_mutex_unlock (&(pool->queue_lock));
break; /**< 当池中空闲线程超过 free_pthread_num则将线程释放回操作系统 */
}
pthread_mutex_unlock (&(pool->queue_lock));
}
pool->current_pthread_num--; /**< 当前池中线程数减1 */
pthread_exit (NULL); /**< 释放线程*/
return (void*)NULL;
}
/****************************************************************
* function name : ThreadPoolConstruct
* functional description : 创建线程池
* input parameter : max_num 线程池可容纳的最大线程数
free_num 线程池允许存在的最大空闲线程,超过则将线程释放回操作系统
* output parameter :
* return value : 线程池指针
* history :
*****************************************************************/
CThread_pool_t* ThreadPoolConstruct(int max_num,int free_num)
{
CThread_pool_t *pool = (CThread_pool_t *) malloc (sizeof (CThread_pool_t));
if (NULL == pool)
{
return NULL;
}
memset(pool, 0, sizeof(CThread_pool_t));
pthread_mutex_init (&(pool->queue_lock), NULL); /**< 初始化互斥锁 */
pthread_cond_init (&(pool->queue_ready), NULL); /**< 初始化条件变量 */
pool->queue_head = NULL;
pool->max_thread_num = max_num; /**< 线程池可容纳的最大线程数 */
pool->cur_queue_size = 0;
pool->current_pthread_task_num = 0;
pool->shutdown = 0;
pool->current_pthread_num = 0;
pool->free_pthread_num = free_num; /**< 线程池允许存在的最大空闲线程 */
pool->threadid = NULL;
pool->threadid = (pthread_t *) malloc (max_num * sizeof (pthread_t));
pool->AddWorkUnlimit = ThreadPoolAddWorkUnlimit; /**< 给函数指针赋值 */
pool->AddWorkLimit = ThreadPoolAddWorkLimit;
pool->Destruct = ThreadPoolDestroy;
pool->GetMaxThreadNum = ThreadPoolGetThreadMaxNum;
pool->GetCurThreadNum = ThreadPoolGetCurrentThreadNum;
pool->GetCurTaskThreadNum = ThreadPoolGetCurrentTaskThreadNum;
pool->GetCurTaskNum = ThreadPoolGetCurrentTaskNum;
int i = 0;
for (i = 0; i < max_num; i++)
{
pool->current_pthread_num++; /**< 当前池中的线程数 */
pthread_create (&(pool->threadid[i]), NULL, ThreadPoolRoutine, (void*)pool); /**< 创建线程 */
usleep(1000);
}
return pool;
}
/****************************************************************
* function name : ThreadPoolConstructDefault
* functional description : 创建线程池,以默认的方式初始化,未创建线程
* input parameter :
* output parameter :
* return value : 线程池指针
* history :
*****************************************************************/
CThread_pool_t* ThreadPoolConstructDefault(void)
{
CThread_pool_t *pool = (CThread_pool_t *) malloc (sizeof (CThread_pool_t));
if (NULL == pool)
{
return NULL;
}
memset(pool, 0, sizeof(CThread_pool_t));
pthread_mutex_init(&(pool->queue_lock), NULL);
pthread_cond_init(&(pool->queue_ready), NULL);
pool->queue_head = NULL;
pool->max_thread_num = DEFAULT_MAX_THREAD_NUM; /**< 默认值 */
pool->cur_queue_size = 0;
pool->current_pthread_task_num = 0;
pool->shutdown = 0;
pool->current_pthread_num = 0;
pool->free_pthread_num = DEFAULT_FREE_THREAD_NUM; /**< 默认值 */
pool->threadid = NULL;
pool->AddWorkUnlimit = ThreadPoolAddWorkUnlimit;
pool->AddWorkLimit = ThreadPoolAddWorkLimit;
pool->Destruct = ThreadPoolDestroy;
pool->GetMaxThreadNum = ThreadPoolGetThreadMaxNum;
pool->GetCurThreadNum = ThreadPoolGetCurrentThreadNum;
pool->GetCurTaskThreadNum = ThreadPoolGetCurrentTaskThreadNum;
pool->GetCurTaskNum = ThreadPoolGetCurrentTaskNum;
return pool;
}
Lib_thread_pool.h:
/************************************************************************
* module : 线程池头文件
* file name : lib_thread_pool.h
* Author :
* version : V1.0
* DATE :
* directory :
* description :
* related document:
*
************************************************************************/
/*-----------------------includes-------------------------------*/
#ifndef __PTHREAD_POOL_H__
#define __PTHREAD_POOL_H__
#include <pthread.h>
/*---------------constants/macro definition---------------------*/
#define DEFAULT_MAX_THREAD_NUM 100
#define DEFAULT_FREE_THREAD_NUM 10
typedef struct worker_t worker_t;
typedef struct CThread_pool_t CThread_pool_t;
/*---------------global variables definition-----------------------*/
/*线程池任务结点*/
struct worker_t
{
void *(*process) (void *arg); /**< 回调函数 */
int paratype; /**< 函数类型(预留) */
void *arg; /**< 回调函数参数 */
struct worker_t *next; /**< 连接下一个任务结点 */
};
/*线程池控制器*/
struct CThread_pool_t
{
pthread_mutex_t queue_lock; /**< 互斥锁 */
pthread_cond_t queue_ready; /**< 条件变量 */
worker_t *queue_head; /**< 任务结点链表,保存所有投递的任务 */
int shutdown; /**< 线程池销毁标志,1 - 销毁 */
pthread_t *threadid; /**< 线程ID */
int max_thread_num; /**< 线程池可容纳的最大线程数 */
int current_pthread_num; /**< 当前线程池存放的线程数 */
int current_pthread_task_num; /**< 当前正在执行任务和已分配任务的线程数目和 */
int cur_queue_size; /**< 当前等待队列的任务数目 */
int free_pthread_num; /**< 线程池内允许存在的最大空闲线程数 */
/****************************************************************
* function name : ThreadPoolAddWorkLimit
* functional description : 向线程池投递任务
* input parameter : pthis 线程池指针
process 回调函数
arg 回调函数的参数
* output parameter :
* return value : 0 - 成功;-1 - 失败
* history :
*****************************************************************/
int (*AddWorkUnlimit)(void* pthis,void *(*process) (void *arg), void *arg);
/****************************************************************
* function name : ThreadPoolAddWorkUnlimit
* functional description : 向线程池投递任务,无空闲线程则阻塞
* input parameter : pthis 线程池指针
process 回调函数
arg 回调函数的参数
* output parameter :
* return value : 0 - 成功;-1 - 失败
* history :
*****************************************************************/
int (*AddWorkLimit)(void* pthis,void *(*process) (void *arg), void *arg);
/****************************************************************
* function name : ThreadPoolGetThreadMaxNum
* functional description : 获取线程池可容纳的最大线程数
* input parameter : pthis 线程池指针
* output parameter :
* return value : 线程池可容纳的最大线程数
* history :
*****************************************************************/
int (*GetMaxThreadNum) (void *pthis);
/****************************************************************
* function name : ThreadPoolGetCurrentThreadNum
* functional description : 获取线程池存放的线程数
* input parameter : pthis 线程池指针
* output parameter :
* return value : 线程池存放的线程数
* history :
*****************************************************************/
int (*GetCurThreadNum) (void *pthis);
/****************************************************************
* function name : ThreadPoolGetCurrentTaskThreadNum
* functional description : 获取当前正在执行任务和已分配任务的线程数目和
* input parameter : pthis 线程池指针
* output parameter :
* return value : 当前正在执行任务和已分配任务的线程数目和
* history :
*****************************************************************/
int (*GetCurTaskThreadNum) (void *pthis);
/****************************************************************
* function name : ThreadPoolGetCurrentTaskNum
* functional description : 获取线程池等待队列任务数
* input parameter : pthis 线程池指针
* output parameter :
* return value : 等待队列任务数
* history :
*****************************************************************/
int (*GetCurTaskNum) (void *pthis);
/****************************************************************
* function name : ThreadPoolDestroy
* functional description : 销毁线程池
* input parameter : pthis 线程池指针
* output parameter :
* return value : 0 - 成功;-1 - 失败
* history :
*****************************************************************/
int (*Destruct) (void *pthis);
};
/*---------------functions declaration--------------------------*/
/****************************************************************
* function name : ThreadPoolConstruct
* functional description : 创建线程池
* input parameter : max_num 线程池可容纳的最大线程数
free_num 线程池允许存在的最大空闲线程,超过则将线程释放回操作系统
* output parameter :
* return value : 线程池指针
* history :
*****************************************************************/
CThread_pool_t* ThreadPoolConstruct(int max_num,int free_num);
/****************************************************************
* function name : ThreadPoolConstructDefault
* functional description : 创建线程池,以默认的方式初始化,未创建线程
* input parameter :
* output parameter :
* return value : 线程池指针
* history :
*****************************************************************/
CThread_pool_t* ThreadPoolConstructDefault(void);
#endif
Makefile:
edit:main.o lib_thread_pool.o
gcc -pthread -o edit main.o lib_thread_pool.o
main.o:main.c lib_thread_pool.h
gcc -pthread -c main.c
lib_thread_pool.o:lib_thread_pool.c lib_thread_pool.h
gcc -pthread -c lib_thread_pool.c
.PHONY : clean
clean:
rm -rf *.o
运行:
Make
./edit
Make clean
程序运行截图:
3.改造属于自己的线程池代码
Threadpool.h:
#ifndef __THREAD_POOL_H__
#define __THREAD_POOL_H__
#include <pthread.h>
/**********************************************************************
任务回调函数,也可根据需要自行修改
*********************************************************************/
typedef void *(*pool_task_f)(void *arg);
/**********************************************************************
任务句柄
*********************************************************************/
typedef struct _task{
pool_task_f process;
/*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/
void *arg;
/*回调函数的参数*/
struct _task *next;}pool_task;
/**********************************************************************
线程池句柄
*********************************************************************/
typedef struct{
pthread_t *threadid;
/* 线程号 */
int threads_limit;
/* 线程池中允许的活动线程数目 */
int destroy_flag;
/* 是否销毁线程池 , 0销毁,1不销毁*/
pool_task *queue_head;
/* 链表结构,线程池中所有等待任务 */
int task_in_queue;
/* 当前等待队列的任务数目 */
pthread_mutex_t queue_lock;
/* 锁 */
pthread_cond_t queue_ready;
/* 条件变量 */
}pool_t;
/*********************************************************************
*功能: 初始化线程池结构体并创建线程
*参数: pool:线程池句柄
* threads_limit:线程池中线程的数量
*返回值: 无
*********************************************************************/
void pool_init(pool_t *pool, int threads_limit);
/*********************************************************************
*功能: 销毁线程池,等待队列中的任务不会再被执行,
* 但是正在运行的线程会一直,把任务运行完后再退出
*参数: 线程池句柄
*返回值: 成功:0,失败非0
*********************************************************************/
int pool_uninit(pool_t *pool);
/*********************************************************************
*功能: 向线程池中添加一个任务
*参数: pool:线程池句柄
* process:任务处理函数
* arg:任务参数
*返回值: 0
*********************************************************************/
int pool_add_task(pool_t *pool, pool_task_f process, void *arg);
#endif
Threadpool.c:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
#include "threadpool.h"
static void *pool_thread_server(void *arg);
/*********************************************************************
*功能: 初始化线程池结构体并创建线程
*参数: pool:线程池句柄
* threads_limit:线程池中线程的数量
*返回值: 无
*********************************************************************/
void pool_init(pool_t *pool, int threads_limit){
pool->threads_limit = threads_limit;
pool->queue_head = NULL; pool->task_in_queue = 0;
pool->destroy_flag = 0;
/*创建存放线程ID的空间*/
pool->threadid = (pthread_t *)calloc(threads_limit, sizeof(pthread_t));
int i = 0;
/*初始化互斥锁和条件变量*/
pthread_mutex_init(&(pool->queue_lock), NULL);
pthread_cond_init(&(pool->queue_ready), NULL);
/*循环创建threads_limit个线程*/
for (i = 0; i < threads_limit; i++){
pthread_create(&(pool->threadid[i]), NULL, pool_thread_server, pool);
}
return;
}
/*********************************************************************
*功能: 销毁线程池,等待队列中的任务不会再被执行,
* 但是正在运行的线程会一直,把任务运行完后再退出
*参数: 线程池句柄*返回值: 成功:0,失败非0
*********************************************************************/
int pool_uninit(pool_t *pool){
pool_task *head = NULL;
int i;
pthread_mutex_lock(&(pool->queue_lock));
if(pool->destroy_flag)/* 防止两次调用 */
return -1;
pool->destroy_flag = 1;
pthread_mutex_unlock(&(pool->queue_lock));
/* 唤醒所有等待线程,线程池要销毁了 */
pthread_cond_broadcast(&(pool->queue_ready));
/* 阻塞等待线程退出,否则就成僵尸了 */
for (i = 0; i < pool->threads_limit; i++)
pthread_join(pool->threadid[i], NULL);
free(pool->threadid);
/* 销毁等待队列 */
pthread_mutex_lock(&(pool->queue_lock));
while(pool->queue_head != NULL){
head = pool->queue_head;
pool->queue_head = pool->queue_head->next;
free(head);
}
pthread_mutex_unlock(&(pool->queue_lock));
/*条件变量和互斥量也别忘了销毁*/
pthread_mutex_destroy(&(pool->queue_lock));
pthread_cond_destroy(&(pool->queue_ready));
return 0;
}
/*********************************************************************
*功能: 向任务队列中添加一个任务
*参数: pool:线程池句柄
* process:任务处理函数
* arg:任务参数*返回值: 无*********************************************************************/
static void enqueue_task(pool_t *pool, pool_task_f process, void *arg){
pool_task *task = NULL;
pool_task *member = NULL;
pthread_mutex_lock(&(pool->queue_lock));
if(pool->task_in_queue >= pool->threads_limit){
printf("task_in_queue > threads_limit!\n");
pthread_mutex_unlock (&(pool->queue_lock));
return;
} task = (pool_task *)calloc(1, sizeof(pool_task));
assert(task != NULL);
task->process = process;
task->arg = arg;
task->next = NULL;
pool->task_in_queue++;
member = pool->queue_head;
if(member != NULL){
while(member->next != NULL)
/* 将任务加入到任务链连的最后位置. */
member = member->next;
member->next = task;
}else{
pool->queue_head = task;
/* 如果是第一个任务的话,就指向头 */ }
printf("\ttasks %d\n", pool->task_in_queue);
/* 等待队列中有任务了,唤醒一个等待线程 */
pthread_cond_signal (&(pool->queue_ready));
pthread_mutex_unlock (&(pool->queue_lock));}
/*********************************************************************
*功能: 从任务队列中取出一个任务
*参数: 线程池句柄
*返回值: 任务句柄
*********************************************************************/
static pool_task *dequeue_task(pool_t *pool){
pool_task *task = NULL;
pthread_mutex_lock(&(pool->queue_lock));
/* 判断线程池是否要销毁了 */
if(pool->destroy_flag){
pthread_mutex_unlock(&(pool->queue_lock));
printf("thread 0x%lx will be destroyed\n", pthread_self());
pthread_exit(NULL);
}
/* 如果等待队列为0并且不销毁线程池,则处于阻塞状态 */
if(pool->task_in_queue == 0){
while((pool->task_in_queue == 0) && (!pool->destroy_flag)){
printf("thread 0x%lx is leisure\n", pthread_self());
/* 注意:pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁 */ pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));
}
}else{
/* 等待队列长度减去1,并取出队列中的第一个元素 */
pool->task_in_queue--;
task = pool->queue_head;
pool->queue_head = task->next;
printf("thread 0x%lx received a task\n", pthread_self());
}
pthread_mutex_unlock(&(pool->queue_lock));
return task;}
/*********************************************************************
*功能: 向线程池中添加一个任务
*参数: pool:线程池句柄
* process:任务处理函数
* arg:任务参数*返回值: 0
*********************************************************************/
int pool_add_task(pool_t *pool, pool_task_f process, void *arg){
enqueue_task(pool, process, arg);
return 0;}
/*********************************************************************
*功能: 线程池服务程序
*参数: 略
*返回值: 略
*********************************************************************/
static void *pool_thread_server(void *arg){
pool_t *pool = NULL;
pool = (pool_t *)arg;
while(1){
pool_task *task = NULL;
task = dequeue_task(pool);
/*调用回调函数,执行任务*/
if(task != NULL){
printf ("thread 0x%lx is busy\n", pthread_self());
task->process(task->arg);
free(task);
task = NULL;
}
}
/*这一句应该是不可达的*/
pthread_exit(NULL);
return NULL;
}
Main.c:
#include <stdio.h>
#include <unistd.h>
#include "threadpool.h"
/*********************************************************************
*功能: 任务处理函数
*参数: 无
*返回值: NULL
*********************************************************************/
void *task_test(void *arg){
printf("\t\tworking on task %d\n", (int)arg);
sleep(1);
/*休息一秒,延长任务的执行时间*/
return NULL;
}
int main (int argc, char *argv[]){
pool_t pool;
int i = 0;
pool_init(&pool, 2);//初始化线程池
sleep(1);
for(i = 0; i < 5; i++){
sleep(1);
pool_add_task(&pool, task_test, (void *)i);//向线程池中添加一个任务
}
sleep(4);
pool_uninit(&pool);//销毁线程池
return 0;
}
运行:
gcc -L/usr/DirectFB25/lib -I/usr/DirectFB25/include/directfb -lpthread -ldl main.c threadpool.c threadpool.h -o edit
./edit
运行截图如下: