天天听别人说服务器开发中的线程池线程池之类的?究竟什么是线程池?实现他的模型是什么样子的?最好在结合实际工作中说一下!!!
如题:????????在下是Linux新手 C++ ?多线程 服务端开发
[解决办法]
比如 A线程不断往a数据组(比如list)中放数据
B线程不断循环处理数据 (会有迭代器++)
A线程放数据的时候会clear掉a数据组中之前的所有数据
B线程此时不能保证迭代器的正确性
为了解决这个问题 就再加入个b数据组 A只操作b
B线程在从a中取数据时候 每次都使看 如果b更新了 就copy过来 没有跟新就一直用之前a中的数据
这样不知是否满足楼主
[解决办法]
因为频繁的开关线程,是一件比较浪费资源的时候,
所以当你程序要一定量线程服务的时候,会在程序启动的时候,
开启一定量的线程,方便后面使用
,这里我以前一个简单例子。看看!
参考一下
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
typedef struct worker
{
void* (*process) (void *arg); //回调函数,任务运行时会调用此函数,注意也可声明成其他形式
void* arg; //回调函数的参数
struct worker *next; //指向下一个任务
} CThread_worker;
/*线程池结构*/
typedef struct
{
pthread_mutex_t queue_lock; //互斥量
pthread_cond_t queue_ready; //条件量
CThread_worker *queue_head; //链表结构,线程池中所有等待任务
int shutdown; //是否销毁线程池
pthread_t* threadid;
int max_thread_num; //线程池中允许的活动线程数目
int cur_queue_size; //当前等待队列的任务数目
} CThread_pool;
int pool_add_worker (void *(*process) (void *arg), void *arg); //往线程池中添加任务
void *thread_routine (void *arg); //线程执行
tatic CThread_pool *pool = NULL; //声明一个线程池的全局变量
void pool_init (int max_thread_num)//初始化线程池
{
pool = (CThread_pool *) malloc (sizeof (CThread_pool));
pthread_mutex_init (&(pool->queue_lock), NULL);
pthread_cond_init (&(pool->queue_ready), NULL);//?
pool->queue_head = NULL;
pool->max_thread_num = max_thread_num;
pool->cur_queue_size = 0;
pool->shutdown = 0;
pool->threadid =(pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
int i = 0;
for (i = 0; i < max_thread_num; i++)
{
pthread_create (&(pool->threadid[i]), NULL, thread_routine,NULL);
}
}
/*向线程池中加入任务*/
int pool_add_worker (void *(*process) (void *arg), void *arg)
{
CThread_worker *newworker =(CThread_worker *) malloc (sizeof (CThread_worker)); //构造一个新任务
newworker->process = process;
newworker->arg = arg;
newworker->next = NULL; //别忘置空
pthread_mutex_lock (&(pool->queue_lock));
CThread_worker *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++;
pthread_mutex_unlock (&(pool->queue_lock));
/*好了,等待队列中有任务了,唤醒一个等待线程;注意如果所有线程都在忙碌,这句没有任何作用*/
pthread_cond_signal (&(pool->queue_ready));
return 0;
}
/*销毁线程池,等待队列中的任务不会再被执行,但是正在运行的线程会一直把任务运行完后再退出*/
int pool_destroy ()
{
if (pool->shutdown) return -1; //防止两次调用
pool->shutdown = 1;
pthread_cond_broadcast (&(pool->queue_ready)); //唤醒所有等待线程,线程池要销毁了
/*阻塞等待线程退出,否则就成僵尸了*/
int i;
for (i = 0; i < pool->max_thread_num; i++)
{
pthread_join (pool->threadid[i], NULL);
}
free (pool->threadid);
/*销毁等待队列*/
CThread_worker *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;
}
void * thread_routine (void *arg)
{
printf ("starting thread 0x%x\n", pthread_self ());
while (1)
{
pthread_mutex_lock (&(pool->queue_lock));
/*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
while (pool->cur_queue_size == 0 && !pool->shutdown)
{
printf ("thread 0x%x is waiting\n", pthread_self ());
pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));
}
/*线程池要销毁了*/
if (pool->shutdown)
{
/*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
pthread_mutex_unlock (&(pool->queue_lock));
printf ("thread 0x%x will exit\n", pthread_self ());
pthread_exit (NULL);
}
printf ("thread 0x%x is starting to work\n", pthread_self ());
assert (pool->cur_queue_size != 0);
assert (pool->queue_head != NULL);
/*等待队列长度减去1,并取出链表中的头元素*/
pool->cur_queue_size--;
CThread_worker *worker = pool->queue_head;
pool->queue_head = worker->next;
pthread_mutex_unlock (&(pool->queue_lock));
/*调用回调函数,执行任务*/
(*(worker->process)) (worker->arg);
free (worker);
worker = NULL;
}
pthread_exit (NULL);
}
// 下面是测试代码
void *myprocess (void *arg)
{
printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *) arg);
sleep (3);/*休息三秒,延长任务的执行时间*/
return NULL;
}
int main (int argc, char **argv)
{
pool_init (3);/*线程池中最多三个活动线程*/
/*连续向池中投入10个任务*/
int *workingnum = (int *) malloc (sizeof (int) * 10);
int i;
for (i = 0; i < 10; i++)
{
workingnum[i] = i;
pool_add_worker (myprocess, &workingnum[i]);
}
/*等待所有任务完成*/
sleep (10);
/*销毁线程池*/
pool_destroy ();
free (workingnum);
return 0;
}
[解决办法]
几个经典的设计模式, 半同步半异步, 领导者追随者.
现在常用one event loop per thread,可以看看陈硕的开源项目和书。
没啥东西,你如果参加工作,这些东西都是天天写的东西。
[解决办法]
先介绍一下 线程的几个状态
线程创建 线程激活 线程挂起 线程终止
不使用线程池的情况是
程序运行过程中 遇到一次需要开线程操作的情况就执行
线程创建 线程激活 线程挂起 线程终止
这些动作都是有花销的
用线程池的情况就是
程序开始 完成 线程创建 之后全部挂起[根据情况]
程序运行中 需要线程只需要将已经创建好的线程中 找一个激活
完成工作之后 继续挂起
程序结束的时候 全部线程终止
对比发现
用于 线程的创建和终止 的花销会减少
以上