一、基于C++11的线程池实现
#ifndef THREAD_POOL_HPP
#define THREAD_POOL_HPP
#include <functional>
#include <iostream>
#include <queue>
#include <thread>
#include <cassert>
#define THREAD_MAX_NUM 3
using namespace std;
class ThreadPool {
private:
bool m_open_flag;
int m_thread_count;
mutex m_mutex_run;
mutex m_mutex_quit;
condition_variable m_cond_run;
condition_variable m_cond_quit;
queue<function<void()>> m_task_queue;
public:
explicit ThreadPool(int thread_count = THREAD_MAX_NUM) {
assert(thread_count > 0);
m_open_flag = true;
m_thread_count = thread_count;
for (int i = 0; i < thread_count; i++) {
thread([this] {
unique_lock<mutex> locker(m_mutex_run);
while (true) {
if (!m_task_queue.empty()) {
auto task = std::move(m_task_queue.front());
m_task_queue.pop();
locker.unlock();
task();
locker.lock();
} else if (!m_open_flag) {
m_thread_count--;
if (m_thread_count == 0) {
m_cond_quit.notify_one();
}
break;
} else {
m_cond_run.wait(locker);
}
}
}).detach();
}
}
~ThreadPool() {
{
unique_lock<mutex> locker(m_mutex_run);
m_open_flag = false;
}
m_cond_run.notify_all();
{
unique_lock<mutex> locker(m_mutex_quit);
m_cond_quit.wait(locker);
}
}
template<class T>
void addTask(T &&task) {
{
unique_lock<mutex> locker(m_mutex_run);
m_task_queue.emplace(std::forward<T>(task));
}
m_cond_run.notify_one();
}
};
void threadFun(int x) {
cout << x << endl;
}
int main() {
ThreadPool thread_pool;
for (int i = 0; i < 10; i++) {
thread_pool.addTask(bind(threadFun, i));
}
}
#endif
atreus@MacBook-Pro % clang++ main.cpp -o main -std=c++11
atreus@MacBook-Pro % ./main
0
3
4
5
6
7
8
9
2
1
atreus@MacBook-Pro %
二、基于C99的线程池实现
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define THREAD_MAX_NUM 3
#define TASK_MAX_NUM 10
typedef struct task_t {
void *(*fun)(void *arg);
void *arg;
struct task_t *next;
} task_t, *task_queue_t;
typedef struct thread_pool_t {
pthread_t *thread_id_list;
int task_cur_num;
task_t *task_queue_head;
task_t *task_queue_tail;
pthread_mutex_t mutex;
pthread_cond_t task_queue_empty;
pthread_cond_t task_queue_not_empty;
pthread_cond_t task_queue_not_full;
} thread_pool_t;
void thread_pool_init(thread_pool_t **thread_pool);
void thread_pool_destroy(thread_pool_t *thread_pool);
void thread_pool_add_task(thread_pool_t *thread_pool, void *(*fun)(void *), void *arg);
void *thread_pool_execute(void *arg);
void *thread_fun(void *arg) {
printf("%d\n", *(int *) arg);
return NULL;
}
int main() {
thread_pool_t *thread_pool;
thread_pool_init(&thread_pool);
int arg[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int i = 0; i < 10; i++) {
thread_pool_add_task(thread_pool, thread_fun, (void *) (arg + i));
}
thread_pool_destroy(thread_pool);
}
void thread_pool_init(thread_pool_t **pool) {
*pool = (thread_pool_t *) calloc(1, sizeof(thread_pool_t));
(*pool)->thread_id_list = (pthread_t *) calloc(THREAD_MAX_NUM, sizeof(pthread_t));
(*pool)->task_cur_num = 0;
(*pool)->task_queue_head = (*pool)->task_queue_tail = NULL;
pthread_mutex_init(&((*pool)->mutex), NULL);
pthread_cond_init(&((*pool)->task_queue_empty), NULL);
pthread_cond_init(&((*pool)->task_queue_not_empty), NULL);
pthread_cond_init(&((*pool)->task_queue_not_full), NULL);
for (int i = 0; i < THREAD_MAX_NUM; i++) {
pthread_create((*pool)->thread_id_list + i, NULL, thread_pool_execute, (void *) *pool);
}
printf("Threadpoll initialized successfully. [thread_pool.c]\n");
}
void thread_pool_destroy(thread_pool_t *pool) {
pthread_mutex_lock(&pool->mutex);
while (pool->task_cur_num != 0) {
pthread_cond_wait(&pool->task_queue_empty, &pool->mutex);
}
pool->task_cur_num = -1;
pthread_mutex_unlock(&pool->mutex);
pthread_cond_broadcast(&pool->task_queue_not_empty);
for (int i = 0; i < THREAD_MAX_NUM; i++) {
pthread_join(pool->thread_id_list[i], NULL);
}
pthread_mutex_destroy(&pool->mutex);
pthread_cond_destroy(&pool->task_queue_empty);
pthread_cond_destroy(&pool->task_queue_not_empty);
pthread_cond_destroy(&pool->task_queue_not_full);
printf("Threadpoll was successfully destroyed. [thread_pool.c]\n");
}
void thread_pool_add_task(thread_pool_t *pool, void *(*fun)(void *), void *arg) {
task_t *new_task = (task_t *) calloc(1, sizeof(task_t));
pthread_mutex_lock(&pool->mutex);
while (pool->task_cur_num == TASK_MAX_NUM) {
pthread_cond_wait(&pool->task_queue_not_full, &pool->mutex);
}
new_task->fun = fun;
new_task->arg = arg;
new_task->next = NULL;
if (pool->task_queue_head == NULL) {
pool->task_queue_head = pool->task_queue_tail = new_task;
pthread_cond_broadcast(&pool->task_queue_not_empty);
} else {
pool->task_queue_tail->next = new_task;
pool->task_queue_tail = new_task;
}
pool->task_cur_num++;
pthread_mutex_unlock(&pool->mutex);
}
void *thread_pool_execute(void *arg) {
thread_pool_t *pool = (thread_pool_t *) arg;
task_t *task = NULL;
while (1) {
pthread_mutex_lock(&pool->mutex);
while (pool->task_cur_num == 0) {
pthread_cond_wait(&pool->task_queue_not_empty, &pool->mutex);
}
if (pool->task_cur_num == -1) {
pthread_mutex_unlock(&pool->mutex);
pthread_exit(NULL);
}
task = pool->task_queue_head;
pool->task_cur_num--;
pthread_cond_broadcast(&pool->task_queue_not_full);
if (pool->task_cur_num == 0) {
pool->task_queue_head = pool->task_queue_tail = NULL;
pthread_cond_broadcast(&pool->task_queue_empty);
} else {
pool->task_queue_head = pool->task_queue_head->next;
}
pthread_mutex_unlock(&pool->mutex);
(*task->fun)(task->arg);
free(task);
task = NULL;
}
}
atreus@MacBook-Pro % clang main.c -o main
atreus@MacBook-Pro % ./main
Threadpoll initialized successfully. [thread_pool.c]
1
4
5
6
7
8
9
0
2
3
Threadpoll was successfully destroyed. [thread_pool.c]
atreus@MacBook-Pro %