多线程排序程序

大憨熊 提交于 2019-12-09 03:49:17

程序描述

此程序实现了多线程的数组排序,可将一个数组拆分为两部分交由两个线程来排序,最后由父进程对其总和。

程序功能实现代码预览

定义一个结构来存排序算法所需要的参数

typedef struct //结构体用来存排序算法需要的参数
{
    int start;
    int end;
}Para;

一个简单的冒泡排序

void sort(Para* para){
    int i,j,temp;
    for(i=para->start;i<para->end;i++){
        for(j=para->end;j>i;j--){
            if(elem[j]<elem[j-1]){
                temp=elem[j];
                elem[j]=elem[j-1];
                elem[j-1]=temp;
            }
        }
    }
    pthread_exit(0);
}

实现对程序计时

int t_start=clock();
int t_end=clock();

将上面的代码分别放在程序首尾,最后相减即可得出运行时间

printf("耗时:%d\n", t_end-t_start);

注:此时间为CPU时间,两个核的话会把两个核的时间加起来。可以在程序名前面加time即可最后得出各种运行时间。

time ./a.out

创建两个线程

pthread_t tid1,tid2;  //线程的identifier
pthread_attr_t attr;  //线程属性

pthread_attr_init(&attr); //初始化默认线程属性

/**
 * 创建执行线程
 */
pthread_create(&tid1,&attr,(void *)sort,&para1); 
pthread_create(&tid2,&attr,(void *)sort,&para2);

重难点解析

关于gcc编译

由于pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。

gcc ./MultithreadsSort.c -lpthread

关于pthread_create

在使用这个方法时,第四个参数非常容易报错,原因是其为void * 类型,所以定义此类方法时参数要定义为void * 类型,然后再在方法中对参数进行格式转换。

void *sort(void * p){
    Para * para=(Para*)p;
    ...
}

完整代码

#include <stdio.h>
#include <pthread.h>
#include <time.h>

#define LENGTH 5000 //宏定义数组长度
#define MAX 100000   //宏定义数取值范围

typedef struct //结构体用来存排序算法需要的参数
{
    int start;
    int end;
}Para;

int elem[LENGTH]; //存随机数
int res[LENGTH];  //存排序结果

void initElem(); //初始化数组,向其中填指定范围的随机数
void *sort(void * p);   //排序程序
void printElenm(int [LENGTH]);  //打印数组用以检验是否排序成功
void merge();  //将elem的结果merge到res中

int main(){

    initElem(); //初始化数组并填入随机数
    /**
     * 设定两个线程各自排序的起止点
     */
    Para para1={0,LENGTH/2};
    Para para2={LENGTH/2+1,LENGTH-1};
    Para para3={0,LENGTH-1};

    pthread_t tid1,tid2;  //线程的identifier
    pthread_attr_t attr;  //线程属性

    pthread_attr_init(&attr); //初始化默认线程属性

    int t_start=clock(); //开始时间
    printf("多线程排序%d 时开始\n", t_start);

    /**
     * 创建执行线程
     */
    pthread_create(&tid1,&attr,sort,&para1); 
    pthread_create(&tid2,&attr,sort,&para2);

    /**
     * 等待线程结束
     */
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);

    merge();  //整合
    //输出结果来验证
    //printElenm(res); 
    int t_end=clock();//结束时刻
    printf("多线程排序%d 时结束\n", t_end);
    printf("多线程排序耗时:%d\n", t_end-t_start); //计算程序运行消耗的时间

    /**
     * 接下来尝试单线程排序
     */
    initElem(); //首先还是初始化数组

    t_start=clock(); //开始时间
    printf("普通排序%d 时开始\n", t_start);

    sort(&para3);

    t_end=clock();//结束时刻
    printf("普通排序%d 时结束\n", t_end);
    printf("普通排序耗时:%d\n", t_end-t_start); //计算程序运行消耗的时间
}

void initElem(){
    srand((unsigned)time(NULL));
    int i;
    for(i=0;i<LENGTH;i++){
        elem[i]=rand()%MAX+1;
    }
}

/**
 * [sort description]
 * 一个简单的冒泡排序算法
 * @param para [description]
 */
void *sort(void * p){
    Para * para=(Para*)p;
    int i,j,temp;
    for(i=para->start;i<para->end;i++){
        for(j=para->end;j>i;j--){
            if(elem[j]<elem[j-1]){
                temp=elem[j];
                elem[j]=elem[j-1];
                elem[j-1]=temp;
            }
        }
    }
    if(para->end-para->start<LENGTH-1){ //如果是部分排序就认为是执行了多线程需要退出,否则不退出
        pthread_exit(0);
    }
}

void printElenm(int num[LENGTH]){
    int i;
    for(i=0;i<LENGTH;i++){
        printf("%d\n", num[i]);
    }
}

void merge(){
    int i=0,j=LENGTH/2+1,k=0;
    while(i<LENGTH/2+1&&j<LENGTH){
        if(elem[i]<elem[j]){
            res[k]=elem[i];
            k++;
            i++;
        }else{
            res[k]=elem[j];
            k++;
            j++;
        }
    }
    if(i<LENGTH/2){
        for(;i<LENGTH/2+1;i++,k++){
            res[k]=elem[i];
        }
    }else{
        for(;j<LENGTH;j++,k++){
            res[k]=elem[j];
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!