1. 程式人生 > >C++:多執行緒程式設計學習:利用多執行緒進行歸併排序。

C++:多執行緒程式設計學習:利用多執行緒進行歸併排序。

首先學習一下簡單的執行緒知識

(1)pthread_join函式,用來阻塞當前的執行緒。直到指定執行緒結束。

(2)pthread_create,用來建立執行緒。

下面的程式碼開了五個執行緒用來輸出一個函式。

#include <pthread.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include "unistd.h"
using namespace
std; #define NUM_THREADS 5 vector<int> read_file(string filename) { ifstream file(filename); int each_element; vector<int> data; if (file){ while(file>>each_element) { data.push_back(each_element); } } return data; } void* say(void
* thread_id) { auto tid = *((int*)(thread_id)); sleep(2*tid); cout<<"hello, ID: "<<tid<<endl; } void* merge_sort(void * arg) { } int main() { pthread_t tids[NUM_THREADS];//define the id of thread int index[NUM_THREADS]; /*for(const auto &x : tids){ cout<<x<<endl; }*/
pthread_attr_t attr; void* status; pthread_attr_init(&attr);// init attr pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);//set attr as not joinable for(size_t i = 0;i!=NUM_THREADS;++i) { index[i] = i; auto ret = pthread_create(&tids[i],NULL,say,(void*)(&index[i])); if (ret){ cout<<"pthread_create error,error code = "<<ret<<endl; } } pthread_attr_destroy(&attr);//destroy the attr and wait other thread for(size_t i = 0;i<NUM_THREADS;++i) { auto ret = pthread_join(tids[i],&status); if (ret){ cout<<"Error:unable to join "<<ret<<endl; exit(-1); } cout<<"main: completed thread id "<<i<<endl; } pthread_exit(NULL); //pthread_create(thread,NULL,merge_sort,) return 0; }

下面的程式碼則是用多執行緒進行歸併排序,由於使用模板引數,該程式可以比較任意的型別的資料。下面說幾個程式設計時遇到的問題

(1):似乎執行緒的目標函式必須是void* 型別的函式,否則編譯不通過。

(2):在傳輸引數的時候,必須將引數封裝在一個結構體裡面,然後將結構體的指標轉換成void*型別。

(3):因為我們要進行模板程式設計,所以要將結構體,以及相應的處理函式都寫成模板的形式。

(4):將資料用vector表示而不是陣列的形式,這樣可用不需要知道資料的長度,結構體內部使用該vector的引用

(5):使用decltype()獲取型別,如該使用decltype(a[0])的形式會獲得一個引用的型別,這不是需要的,所以要利用decltype(a);

#include <pthread.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cstdlib>
#include <typeinfo>
#include <algorithm>
#include "unistd.h"
using namespace std;
#define NUM_THREADS 5


template<typename T>
struct Leninfo
{
       Leninfo(int _l,int _h,T& _arr):l(_l),h(_h),arr(_arr){}
        int l;
        int h;
        T& arr;
};
vector<int> read_file(string filename)
{
    ifstream file(filename);
    int each_element;
    vector<int> data;
    if (file){
        while(file>>each_element) {
            data.push_back(each_element);
        }
    }
    return data;
}

template<typename T>
void my_merge(T& arr,int l,int mid,int r)
{

    size_t i = 0,j = 0,k = l;
    size_t bound1 = mid-l,bound2 = r-mid;
    T first;
    T second;
    for(size_t i = l;i!=mid;++i){first.push_back(arr[i]);}
    for(size_t i = mid;i!=r;++i){second.push_back(arr[i]);}
    while(i<bound1 & j<bound2)
    {
        if (first[i]<second[j]){ arr[k++] = first[i++];}
        else{arr[k++] = second[j++];}
    }

     while (i<bound1){arr[k++] = first[i++]; }
     while (j<bound2){arr[k++] = second[j++];}
}

template<typename T>
void* merge_sort(void* info)// merge the arr[l]->arr[h-1]
{

    auto arg = (Leninfo<T>*)(info);
    size_t l = arg->l,h = arg->h;
    T& arr = arg->arr;

    if (h-l < 5) { sort(arr.begin()+l,arr.begin()+h);
    return NULL;}

    pthread_t tid1,tid2;
    auto mid = (l+h)>>1;
    Leninfo<T> info1 = Leninfo<T>(l,mid,arr),info2 = Leninfo<T>(mid,h,arr);

    pthread_create(&tid1,NULL,merge_sort<T>,(void*)(&info1));  //merge_sort(l,mid);
    pthread_create(&tid2,NULL,merge_sort<T>,(void*)(&info2));//merge_sort(mid,h);

    void *status1,*status2;
    pthread_join(tid1,&status1);
    pthread_join(tid2,&status2);
    my_merge(arr,l,mid,h);
}

int main()
{
    void* status;
    pthread_t tids;//define the id of thread
    vector<string> data = {"azcd","afgh","z","hijk","sdf","hlus"};
    auto s = Leninfo<vector<string>>(0,data.size(),data);
    pthread_create(&tids,NULL,merge_sort<decltype(data)>,(void*)&(s));
    pthread_join(tids,&status);
    for(const auto &x : data){cout<<x<<endl;}
    pthread_exit(NULL);
    return 0;
}