面试题答案
一键面试- 数据结构设计:
- 线程池结构体:
typedef struct ThreadPool { pthread_t *threads; // 线程数组 int thread_count; // 当前线程池中的线程数量 int max_thread_count; // 线程池最大线程数量 int min_thread_count; // 线程池最小线程数量 int queue_size; // 任务队列大小 int head; // 任务队列头 int tail; // 任务队列尾 int count; // 任务队列中任务数量 void **task_queue; // 任务队列 pthread_mutex_t lock; // 互斥锁,保护任务队列 pthread_cond_t not_empty; // 条件变量,任务队列非空 pthread_cond_t not_full; // 条件变量,任务队列非满 int shutdown; // 线程池是否关闭标志 } ThreadPool;
- 任务结构体:
typedef struct Task { void (*func)(void *); // 任务执行函数 void *arg; // 任务执行函数的参数 } Task;
- 线程池结构体:
- 函数逻辑:
- 初始化线程池:
ThreadPool* createThreadPool(int min_count, int max_count, int queue_size) { ThreadPool *pool = (ThreadPool *)malloc(sizeof(ThreadPool)); if (!pool) return NULL; pool->min_thread_count = min_count; pool->max_thread_count = max_count; pool->thread_count = min_count; pool->queue_size = queue_size; pool->head = 0; pool->tail = 0; pool->count = 0; pool->shutdown = 0; pool->threads = (pthread_t *)malloc(max_count * sizeof(pthread_t)); pool->task_queue = (void **)malloc(queue_size * sizeof(void *)); pthread_mutex_init(&pool->lock, NULL); pthread_cond_init(&pool->not_empty, NULL); pthread_cond_init(&pool->not_full, NULL); for (int i = 0; i < min_count; i++) { pthread_create(&pool->threads[i], NULL, worker, (void *)pool); } return pool; }
- 工作线程函数:
void* worker(void *arg) { ThreadPool *pool = (ThreadPool *)arg; while (1) { pthread_mutex_lock(&pool->lock); while (pool->count == 0 &&!pool->shutdown) { pthread_cond_wait(&pool->not_empty, &pool->lock); } if (pool->shutdown && pool->count == 0) { pthread_mutex_unlock(&pool->lock); pthread_exit(NULL); } Task *task = (Task *)pool->task_queue[pool->head]; pool->head = (pool->head + 1) % pool->queue_size; pool->count--; pthread_cond_signal(&pool->not_full); pthread_mutex_unlock(&pool->lock); (*(task->func))(task->arg); free(task); } return NULL; }
- 添加任务到线程池:
int addTask(ThreadPool *pool, void (*func)(void *), void *arg) { pthread_mutex_lock(&pool->lock); while (pool->count == pool->queue_size &&!pool->shutdown) { pthread_cond_wait(&pool->not_full, &pool->lock); } if (pool->shutdown) { pthread_mutex_unlock(&pool->lock); return -1; } Task *task = (Task *)malloc(sizeof(Task)); task->func = func; task->arg = arg; pool->task_queue[pool->tail] = task; pool->tail = (pool->tail + 1) % pool->queue_size; pool->count++; pthread_cond_signal(&pool->not_empty); // 动态调整线程数,任务队列满且当前线程数小于最大线程数时,增加线程 if (pool->count == pool->queue_size && pool->thread_count < pool->max_thread_count) { pthread_create(&pool->threads[pool->thread_count], NULL, worker, (void *)pool); pool->thread_count++; } pthread_mutex_unlock(&pool->lock); return 0; }
- 销毁线程池:
void destroyThreadPool(ThreadPool *pool) { pthread_mutex_lock(&pool->lock); pool->shutdown = 1; pthread_cond_broadcast(&pool->not_empty); pthread_cond_broadcast(&pool->not_full); pthread_mutex_unlock(&pool->lock); for (int i = 0; i < pool->thread_count; i++) { pthread_join(pool->threads[i], NULL); } for (int i = 0; i < pool->count; i++) { Task *task = (Task *)pool->task_queue[i]; free(task); } free(pool->threads); free(pool->task_queue); pthread_mutex_destroy(&pool->lock); pthread_cond_destroy(&pool->not_empty); pthread_cond_destroy(&pool->not_full); free(pool); }
- 初始化线程池:
- 动态调整线程池大小:
- 增加线程:在
addTask
函数中,当任务队列满(pool->count == pool->queue_size
)且当前线程数小于最大线程数(pool->thread_count < pool->max_thread_count
)时,通过pthread_create
创建新的线程,加入到线程池中。 - 减少线程:可以定期检查线程的忙碌状态(例如增加一个标志位记录线程是否在执行任务),当发现有过多的空闲线程(线程数大于最小线程数且有线程长时间空闲)时,可以让空闲线程退出。具体实现可在工作线程函数
worker
中添加逻辑,当满足空闲条件且线程数大于最小线程数时,线程自行退出。例如,在worker
函数获取任务前,记录当前时间戳,若等待任务时间超过一定阈值且线程数大于最小线程数,线程可以调用pthread_exit
退出。 - 注意事项:在动态调整线程大小时,要注意对共享资源(如任务队列、线程数量等)的保护,使用互斥锁来确保数据一致性,避免出现竞态条件。同时,在条件变量的使用上要合理,确保线程能够正确地等待和唤醒。
- 增加线程:在