main线程
1. 创建线程池
2. 主线程往阻塞队列中放任务; 子线程从阻塞队列中取任务,然后执行任务
3. 线程池优雅地退出
4. 销毁线程池
#ifndef __WD_BLOCKQ_H
#define __WD_BLOCKQ_H
#include <func.h>
#define N 1024
typedef int E;
typedef struct {
E elements[N];
int front;
int rear;
int size;
pthread_mutex_t mutex;
pthread_cond_t not_empty;
pthread_cond_t not_full;
} BlockQ;
BlockQ* blockq_create(void);
void blockq_destroy(BlockQ* q);
void blockq_push(BlockQ* q, E val);
E blockq_pop(BlockQ* q);
E blockq_peek(BlockQ* q);
bool blockq_empty(BlockQ* q);
bool blockq_full(BlockQ* q);
#endif
#include "BlockQ.h"
BlockQ* blockq_create(void) {
BlockQ* q = (BlockQ*)calloc(1, sizeof(BlockQ));
pthread_mutex_init(&q->mutex, NULL);
pthread_cond_init(&q->not_empty, NULL);
pthread_cond_init(&q->not_full, NULL);
return q;
}
void blockq_destroy(BlockQ* q) {
pthread_mutex_destroy(&q->mutex);
pthread_cond_destroy(&q->not_empty);
pthread_cond_destroy(&q->not_full);
free(q);
}
void blockq_push(BlockQ* q, E val) {
pthread_mutex_lock(&q->mutex);
while (q->size == N) {
pthread_cond_wait(&q->not_full, &q->mutex);
}
q->elements[q->rear] = val;
q->rear = (q->rear + 1) % N;
q->size++;
pthread_cond_signal(&q->not_empty);
pthread_mutex_unlock(&q->mutex);
}
E blockq_pop(BlockQ* q) {
pthread_mutex_lock(&q->mutex);
while (q->size == 0) {
pthread_cond_wait(&q->not_empty, &q->mutex);
}
E retval = q->elements[q->front];
q->front = (q->front + 1) % N;
q->size--;
pthread_cond_signal(&q->not_full);
pthread_mutex_unlock(&q->mutex);
return retval;
}
E blockq_peek(BlockQ* q) {
pthread_mutex_lock(&q->mutex);
while (q->size == 0) {
pthread_cond_wait(&q->not_empty, &q->mutex);
}
E retval = q->elements[q->front];
pthread_mutex_unlock(&q->mutex);
return retval;
}
bool blockq_full(BlockQ* q) {
pthread_mutex_lock(&q->mutex);
int size = q->size;
pthread_mutex_unlock(&q->mutex);
return size == N;
}
bool blockq_empty(BlockQ* q) {
pthread_mutex_lock(&q->mutex);
int size = q->size;
pthread_mutex_unlock(&q->mutex);
return size == 0;
}
#include <func.h>
#include "BlockQ.h"
typedef struct {
pthread_t* threads;
int nums;
BlockQ* q;
} ThreadPool;
void* start_routine(void* args) {
ThreadPool* pool = (ThreadPool*) args;
pthread_t tid = pthread_self();
while (1) {
E task_id = blockq_pop(pool->q);
if (task_id == -1) {
pthread_exit(NULL);
}
printf("%lx: execute task %d\n", tid, task_id);
sleep(3);
printf("%lx: task %d done\n", tid, task_id);
}
return NULL;
}
ThreadPool* threadpool_create(int n) {
ThreadPool* pool = (ThreadPool*)malloc(sizeof(ThreadPool));
pool->threads = (pthread_t*)malloc(n * sizeof(pthread_t));
pool->nums = n;
pool->q = blockq_create();
for(int i = 0; i < n; i++) {
pthread_create(pool->threads + i, NULL, start_routine, (void*)pool);
}
return pool;
}
void threadpool_destroy(ThreadPool* pool) {
blockq_destroy(pool->q);
free(pool->threads);
free(pool);
}
int main(int argc, char* argv[])
{
ThreadPool* pool = threadpool_create(8);
for(int i = 0; i < 100; i++) {
blockq_push(pool->q, i + 1);
}
sleep(5);
for (int i = 0; i < pool->nums; i++) {
blockq_push(pool->q, -1);
}
for(int i = 0; i < pool->nums; i++) {
pthread_join(pool->threads[i], NULL);
}
threadpool_destroy(pool);
return 0;
}