linux pool函数,Linux 线程池,执行任务队列(生产者消费者模型)

两个结构体

线程池

391c1bab7d5c

线程池结构体包含任务队列和线程数组两个结构体,和一些锁,条件变量,长度等成员

任务

391c1bab7d5c

任务队列是一个链表结构,链表中每个任务是一个函数指针做任务句柄

任务队列是线程和主程序所共享的共享资源,所以要考虑互斥的对任务队列中入队和出对进行操作。主程序向任务队列中加任务,线程从任务队列中取任务,考虑用条件变量来模拟操作系统中的生产者消费者模型,即pv操作

四个函数

void pool_init(int max_thread_num)

391c1bab7d5c

初始化线程池,对线程池各成员进行初始化。根据传入参数初始化n个线程;

int pool_add_worker(void(process)(void *arg),void *arg)

391c1bab7d5c

此函数是main函数向任务队列中加任务,相当于pv操作的v操作。此时用到链表的知识,新建一个链表项,链表项中传入任务要完成的函数句柄,之后将链表项插入到队尾。注意互斥访问任务队列。

void *thread_routine(void *arg)

函数太长截屏不下来。参照下面完整代码

这是线程内部运行过程,即pthread_create时传入的函数句柄。此线程相当于消费者,从任务队列中取任务并执行。逻辑判断参照下面的补充部分。

int pool_destory()

391c1bab7d5c

线程池销毁以及资源回收。shutdown 置1,;broadcast唤醒所有等待线程使其exit退出;join掉所有的线程;free回收为线程malloc的堆空间,线程数组,free一次就行;free掉当前任务队列中所有的任务,因为链表结构,每一个链表项都要free掉;销毁互斥锁和条件变量,最后free掉pool结构体。

补充

线程在运行时对当前任务队列长度和当前线程池状态(shutdown)的判断是很重要的(见thread_routine代码)

没有任务+线程池开 : wait挂起等待生产者(main)加任务,之后进入临界区

没有任务+线程池关 : wait时被pool_destory函数将shutdown置1并且(broadcast)唤醒所有挂起等待的线程,此时线程再次循环发现shutdown为1会exit退出。

有任务+线程池开 : 向下进入临界区

391c1bab7d5c

个人收获

复习生产者消费者模型

复习链表用法

复习内存操作:malloc的数组free一次,链表每个链表项要分别分配空间和回收,回收后指针及时赋空防止野指针

完整代码

#include

#include

using namespace std;

#include

#include

#include

typedef struct worker

{

void *(*process) (void *arg);//任务句柄,函数指针

void *arg;//函数参数

struct worker * next;//链表指向下一个任务

}CThread_worker;

typedef struct threadpool

{

pthread_mutex_t queue_lock;

pthread_cond_t queue_ready;

CThread_worker *queue_head;//任务队列,链表结构

pthread_t *threadid;//线程池中的线程,数组结构

int max_thread_num;//线程池中线程数

int cur_queue_size;//当前任务队列中任务数

int shutdown;//线程池是否启用

}CThread_pool;

int pool_add_worker(void*(*process)(void *arg),void *arg);

void *thread_routine(void *arg);

static 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;//running

pool->threadid = (pthread_t*)malloc(max_thread_num*sizeof(pthread_t));

int i = 0;

for(i = 0;i

{

pthread_create(&(pool->threadid[i]),NULL,thread_routine,NULL);

}

}

int pool_add_worker(void*(*process)(void *arg),void *arg)

{//chain add 1,v

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);

pool->cur_queue_size++;

pthread_mutex_unlock(&(pool->queue_lock));

pthread_cond_signal(&(pool->queue_ready));//notice thread

return 0;

}

int pool_destory()

{//Recycling resources

if(pool->shutdown)//avoid multy-shutdown

{ return -1;}

pool->shutdown = 1;

pthread_cond_broadcast(&(pool->queue_ready));

//join threads

int i;

for(i=0;imax_thread_num;i++)

{

pthread_join(pool->threadid[i],NULL);

}

free(pool->threadid);//malloc

//destory queue_worker

CThread_worker *head = NULL;

while(pool->queue_head!=NULL);

{

head = pool->queue_head;

pool->queue_head = pool->queue_head->next;

free(head);

}

//destory mutex& cond

pthread_mutex_destroy(&(pool->queue_lock));

pthread_cond_destroy(&(pool->queue_ready));

free(pool);

pool = NULL;

return 0;

}

void *thread_routine(void *arg)

{//p

cout << "thread" << pthread_self() << "is running!" << endl;

while(1)

{

pthread_mutex_lock(&(pool->queue_lock));

while(pool->cur_queue_size==0&&pool->shutdown==0)

{

cout << "thread" << pthread_self() << "is waiting" << endl;

pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));

}

if(pool->shutdown == 1)

{

pthread_mutex_unlock(&(pool->queue_lock));

cout << "thread" << pthread_self() << "will eixt" << endl;

pthread_exit(NULL);

}

//************Critical area

cout << "thread" << pthread_self() << "is going to work" << endl;

assert(pool->cur_queue_size!=0);

assert(pool->queue_head!=NULL);

//queue pop

pool->cur_queue_size--;

CThread_worker * worker = pool->queue_head;

pool->queue_head = worker->next;

//*************Critical area

//put out source(worker) to operate

pthread_mutex_unlock(&(pool->queue_lock));

(*(worker->process))(worker->arg);

free(worker);

worker = NULL;

}

pthread_exit(NULL);

}

void *myprocess(void *arg)

{

cout << "thread" << pthread_self() << "is working on task " << *(int *)arg << endl;

sleep(1);

return NULL;

}

int main()

{

pool_init(3);

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(5);

pool_destory();

free(workingnum);

return 0;

}

### 回答1: 下面是一个使用 Qt 线程池实现生产者与消费者模型的简单示例: ```cpp #include <QtCore> #include <iostream> class Producer : public QObject { Q_OBJECT public: Producer(QThreadPool *pool, QMutex *mutex, QWaitCondition *cond, QList<int> *data) : m_pool(pool), m_mutex(mutex), m_cond(cond), m_data(data) { m_count = 0; } public slots: void produce() { int num = qrand() % 100; QRunnable *task = new Task(num, m_mutex, m_cond, m_data); m_pool->start(task); m_count++; std::cout << "Produced " << num << std::endl; m_cond->wakeAll(); } int count() const { return m_count; } private: QThreadPool *m_pool; QMutex *m_mutex; QWaitCondition *m_cond; QList<int> *m_data; int m_count; }; class Consumer : public QObject { Q_OBJECT public: Consumer(QMutex *mutex, QWaitCondition *cond, QList<int> *data) : m_mutex(mutex), m_cond(cond), m_data(data) { } public slots: void consume() { m_mutex->lock(); while (m_data->isEmpty()) { m_cond->wait(m_mutex); } int num = m_data->takeFirst(); std::cout << "Consumed " << num << std::endl; m_mutex->unlock(); } private: QMutex *m_mutex; QWaitCondition *m_cond; QList<int> *m_data; }; class Task : public QRunnable { public: Task(int num, QMutex *mutex, QWaitCondition *cond, QList<int> *data) : m_num(num), m_mutex(mutex), m_cond(cond), m_data(data) { } void run() { m_mutex->lock(); while (m_data->size() >= 10) { m_cond->wait(m_mutex); } m_data->append(m_num); m_mutex->unlock(); } private: int m_num; QMutex *m_mutex; QWaitCondition *m_cond; QList<int> *m_data; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qsrand(QTime::currentTime().msec()); QThreadPool pool; pool.setMaxThreadCount(5); QMutex mutex; QWaitCondition cond; QList<int> data; Producer producer(&pool, &mutex, &cond, &data); Consumer consumer(&mutex, &cond, &data); QObject::connect(&producer, &Producer::produce, &consumer, &Consumer::consume); QTimer timer; QObject::connect(&timer, &QTimer::timeout, &producer, &Producer::produce); timer.start(1000); QTimer countTimer; QObject::connect(&countTimer, &QTimer::timeout, [&producer]() { std::cout << "Produced " << producer.count() << " items" << std::endl; }); countTimer.start(5000); return app.exec(); } ``` 在上面的示例中,`Producer` 和 `Consumer` 类继承自 `QObject`,并使用 Qt 信号和槽机制进行通信。`Producer` 类的 `produce()` ### 回答2: Qt线程池可以很好地实现生产者与消费者模型。生产者与消费者模型主要是通过一个共享的缓冲区来实现生产者生产数据,消费者消费数据的过程。下面是一个使用Qt线程池实现生产者与消费者模型的示例: 1. 定义一个数据结构,用于存储生产者和消费者共享的数据。这个数据结构可以是一个队列或者一个列表。 2. 创建一个Qt线程池,并设置线程池的最大线程数。 3. 创建生产者线程和消费者线程,并将它们添加到线程池中。 4. 在生产者线程中,生产数据并将数据添加到共享的数据结构中。可以使用Qt的信号槽机制,在生产者线程中发送信号,将数据发送给消费者线程。 5. 在消费者线程中,从共享的数据结构中获取数据并进行消费。可以使用Qt的信号槽机制,在消费者线程中接收信号,并处理收到的数据。 6. 在主线程中,等待生产者线程和消费者线程完成工作,并关闭线程池。 通过使用Qt线程池,可以方便地管理多个线程,避免手动管理线程的创建和销毁,从而简化了生产者与消费者模型的实现。此外,Qt的信号槽机制可以方便地实现线程间的通信,从而实现生产者与消费者之间的数据传递。 ### 回答3: Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的类库和工具,其中也包括线程池的实现。在Qt中,可以使用QThreadPool类来创建和管理线程池。 生产者与消费者模型是一种常见的多线程编程模型,其中有一组线程作为生产者,负责生成数据,另一组线程作为消费者,负责处理这些数据。线程池可以很好地支持这种模型,并提供了以下步骤来实现: 1. 创建一个线程池对象:使用QThreadPool类创建一个线程池对象,设置最大线程数、线程闲置时间等属性。 2. 创建生产者线程:通过继承QRunnable类,实现自己的生产者线程类。在类中重写run()函数,在其中完成需要生产的数据的生成。 3. 创建消费者线程:同样通过继承QRunnable类,实现自己的消费者线程类。在类中重写run()函数,在其中完成对生产者生成的数据的处理。 4. 将任务添加到线程池使用QThreadPool的start()函数将生产者和消费者线程对象添加到线程池中,线程池会自动分配线程去运行这些任务。 5. 等待线程池完成任务:可以使用QThreadPool的waitForDone()函数来等待线程池中的所有任务完成,确保所有生产者和消费者线程都执行完毕。 通过以上步骤,我们可以在Qt中实现简单的生产者与消费者模型线程池可以很好地管理线程的创建和销毁,提高线程利用率和系统的性能。同时,Qt的线程池也提供了一些其他的功能,比如任务优先级和取消线程等,可以根据实际需求来灵活调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值