多线程-生产者消费者模式(1)

这种模型应该也可以归类为生产者消费者模型,但是我觉得这种实现方法效率应该没有用队列来实现效率高。后面再用队列来实现一次。
Figure1
这个图就是这个程序所要实现的。

先定义两个结构体,thread_sync_t是保存着生产者和消费者共享的资源数组,thread_var是用来记录这个线程应该处理共享资源中哪一个资源的位置。

struct thread_sync_t{
    string* imagePath;
    bool* collectFinish;
    pthread_mutex_t* collectAndSend;
    pthread_cond_t* collectReady;
};

struct thread_var{
    int threadIndex;
    thread_sync_t* sync;
};

一个生产者线程和多个消费者线程,我这里生产者线程是CollectImages,消费者线程是SendImages。
CollectImages每隔1秒,产生张图片,并发出信号,请求发送进程处理。
SendImages处理一张图片需要2秒。
都是些模板代码,没什么好解释的。

对这些线程共享变量的初始化,每个线程都是共享thread_sync_t这个结构体的对象。

    collectThread = new pthread_t[collectThreadCnt];
    sendThread = new pthread_t[sendThreadCnt];
    threadVar = new thread_var[sendThreadCnt];
    InitThreadVar(threadVar);
void InitThreadVar(thread_var* arg){
    thread_sync_t* psync = new thread_sync_t;

    psync->imagePath = new string[sendThreadCnt];
    psync->collectAndSend = new pthread_mutex_t[sendThreadCnt];
    psync->collectReady = new pthread_cond_t[sendThreadCnt];
    psync->collectFinish = new bool[sendThreadCnt];

    for(int i = 0; i < sendThreadCnt; ++i){
        pthread_mutex_init(&psync->collectAndSend[i], NULL);
        pthread_cond_init(&psync->collectReady[i], NULL);
        psync->collectFinish[i] = false;
    }
    for(int i = 0; i < sendThreadCnt; ++i){
        arg[i].threadIndex = i;
        arg[i].sync = psync;
    }
}

全部源代码

#include <iostream>
#include "util/DBHelper.h"
#include <pthread.h>
#include <string>
#include <cstring>
#include <ctime>
#include <sstream>
#include <unistd.h>

using namespace std;

void* CollectImages(void*);
void* SendImages(void*);
void err_exit(int, string);

struct thread_sync_t{
    string* imagePath;
    bool* collectFinish;
    pthread_mutex_t* collectAndSend;
    pthread_cond_t* collectReady;
};

struct thread_var{
    //int cameraIndex;
    int threadIndex;
    thread_sync_t* sync;
//    string imagePath;
//    bool collectFinish;
//    pthread_mutex_t* collectAndSend;
//    pthread_cond_t* collectReady;
};

void InitThreadVar(thread_var*);
void DestoryThreadVar(thread_var*);

pthread_t* sendThread;
pthread_t* collectThread;
thread_var* threadVar;
int collectThreadCnt = 1;
int sendThreadCnt = 10;

int main() {
    int err;


    collectThread = new pthread_t[collectThreadCnt];
    sendThread = new pthread_t[sendThreadCnt];
    threadVar = new thread_var[sendThreadCnt];
    InitThreadVar(threadVar);

    for(int i = 0; i < collectThreadCnt; ++i){
        err = pthread_create(&collectThread[i], NULL, CollectImages, (void*)threadVar);
        if(err != 0){
            err_exit(err, "create thread error");
        }
    }


    for(int i = 0; i < sendThreadCnt; ++i){
        err = pthread_create(&sendThread[i], NULL, SendImages, (void*)(threadVar + i));
        if(err != 0){
            err_exit(err, "create thread error");
        }
    }

    while(1){

    }
    return 0;
}

void InitThreadVar(thread_var* arg){
    thread_sync_t* psync = new thread_sync_t;

    psync->imagePath = new string[sendThreadCnt];
    psync->collectAndSend = new pthread_mutex_t[sendThreadCnt];
    psync->collectReady = new pthread_cond_t[sendThreadCnt];
    psync->collectFinish = new bool[sendThreadCnt];

    for(int i = 0; i < sendThreadCnt; ++i){
        pthread_mutex_init(&psync->collectAndSend[i], NULL);
        pthread_cond_init(&psync->collectReady[i], NULL);
        psync->collectFinish[i] = false;
    }
    for(int i = 0; i < sendThreadCnt; ++i){
        arg[i].threadIndex = i;
        arg[i].sync = psync;
    }


}

void DestoryThreadVar(thread_var* arg){

}

void* CollectImages(void* arg){
    bool cond = false;
    while(1){

        srand((int)time(0));

        for(int threadIndex = 0; threadIndex < sendThreadCnt; ++threadIndex){
            thread_var* threadArg = &((thread_var*) arg)[threadIndex];

            //cout << "thread: " << threadIndex << " collect image before lock" <<endl;
            pthread_mutex_lock(&threadArg->sync->collectAndSend[threadIndex]);
            //cout << "thread: " << threadIndex << " collect image lock" <<endl;
            int r = rand() % sendThreadCnt;
            stringstream ss;
            ss << "/home/honkee/Downloads/photo/" << r << ".jpg";
            ss >> threadArg->sync->imagePath[threadIndex];
            threadArg->sync->collectFinish[threadIndex] = true;
            cout << "thread: " << threadIndex << " collect finish: "
                    << threadArg->sync->imagePath[threadIndex] << endl <<flush;

            pthread_cond_signal(&threadArg->sync->collectReady[threadIndex]);
            pthread_mutex_unlock(&threadArg->sync->collectAndSend[threadIndex]);
            //cout << "thread: " << threadIndex << " collect image unlock" <<endl;
            sleep(1);
        }


        if(cond){
            break;
        }
    }
    printf("collect image thread\n");

}

void* SendImages(void* arg){
    thread_var* threadArg = (thread_var*) arg;
    bool cond = false;
    while(1){
        int threadIndex = threadArg->threadIndex;
        //cout << "thread: " << threadIndex << " send image before lock" <<endl;
        pthread_mutex_lock(&threadArg->sync->collectAndSend[threadIndex]);
        //cout << "thread: " << threadIndex << " send image lock" <<endl;

        while(threadArg->sync->collectFinish[threadIndex] == false){
            cout << "thread: "<< threadIndex << " waiting..." <<endl <<flush;

            pthread_cond_wait(&threadArg->sync->collectReady[threadIndex],
                                &threadArg->sync->collectAndSend[threadIndex]);
        }
        cout << "thread: " << threadIndex << " send finish: "
                << threadArg->sync->imagePath[threadIndex] << endl <<flush;
        threadArg->sync->collectFinish[threadIndex] = false;

        sleep(2);
        pthread_mutex_unlock(&threadArg->sync->collectAndSend[threadIndex]);
        //cout << "thread: " << threadIndex << " send image unlock" <<endl;

        if(cond){
            break;
        }
    }

    printf("send image thread\n");
}

void err_exit(int err, string str){
    printf("%d: %s\n", err, str.c_str());
    exit(err);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值