windows qt 使用c++ posix接口編寫多線程程序(一)

一、多線程是多任務處理的一種特殊形式,多任務處理允許讓電腦同時運行兩個或兩個以上的程序。一般情況下,兩種類型的多任務處理:基於進程和基於線程基於進程的多任務處理是程序的併發執行。基於線程的多任務處理是同一程序的片段的併發執行。多線程程序包含可以同時運行的兩個或多個部分。這樣的程序中的每個部分稱爲一個線程,每個線程定義了一個單獨的執行路徑,C++ 不包含多線程應用程序的任何內置支持。相反,它完全依賴於操作系統來提供此功能

二、多線程的案例(以下案例都在windows qt 環境下編譯運行)

1. 多線程實現

#include <iostream>
//#include <pthread.h>
#include <time.h>
#include "pthread.h"

using namespace std;

#define NUM_THREADS 5

//c++ 中實現延時函數
void delay(int sec)
{
    time_t start_time, cur_time; // 變量聲明
    time(&start_time);
    do {
    time(&cur_time);
    } while((cur_time - start_time) < sec );
}

void *say_hello(void *threadid){
    //對傳入的參數進行強制類型轉換
    int tid = *((unsigned short *)threadid);
    cout << "Hello Runoob! 線程ID, "<< tid << endl;
    pthread_exit(NULL);
}

int main(){
    //定義線程id變量
    pthread_t tids[NUM_THREADS];
    int indexes[NUM_THREADS];
    for(int i = 0;i < NUM_THREADS; ++i){
        cout << "main() : 創建線程, " << i << endl;
        indexes[i] = i;//先保存i的值
        int ret = pthread_create(&tids[i],NULL,say_hello,(void *)&indexes[i]);
        if(ret != 0){
            cout << "pthread_create error : error_code="<< ret << endl;
        }
    }
    delay(2);
    pthread_exit(NULL);
    return 0;
}
上述案例使用pthread_create創建線程,參數可以傳入線程入口地址,調用成功後直接進入線程入口函數,入口函數代碼即爲線程體,在線程體執行完畢後調用pthread_exit結束線程,main函數就是一主線程,在其創建的線程都是其子線程,子線程依附於主線程,若主線程提前結束,子線程也會退出,爲了保證子線程能夠正常退出,在main線程中執行了delay 動作保證子線程有足夠的時間調度執行。

執行效果:

main() : 創建線程, 0
main() : 創建線程, 1
Hello Runoob! 線程ID, 0
main() : 創建線程, 2
main() : 創建線程, 3
Hello Runoob! 線程ID, 2
main() : 創建線程, 4
Hello Runoob! 線程ID, 1
Hello Runoob! 線程ID, 3
Hello Runoob! 線程ID, 4

2.線程的分離和鏈接

在任何一個時間點上,線程是可結合的(joinable),或者是分離的(detached)。一個可結合的線程能夠被其他線程收回其資源和殺死;在被其他線程回收之前,它的存儲器資源(如棧)是不釋放的。相反,一個分離的線程是不能被其他線程回收或殺死的,它的存儲器資源在它終止時由系統自動釋放。線程的分離狀態決定一個線程以什麼樣的方式來終止自己。在默認情況下線程是非分離狀態的,這種情況下,原有的線程等待創建的線程結束。只有當pthread_join()函數返回時,創建的線程纔算終止,才能釋放自己佔用的系統資源。而分離線程不是這樣子的,它沒有被其他的線程所等待,自己運行結束了,線程也就終止了,馬上釋放系統資源。程序員應該根據自己的需要,選擇適當的分離狀態。所以如果我們在創建線程時就知道不需要了解線程的終止狀態,則可以pthread_attr_t結構中的detachstate線程屬性,讓線程以分離狀態啓動.

代碼如下:

#include <iostream>
using namespace std;

#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <windows.h>

#define NUM_THREADS 5

void *wait(void *t){
   int i;
   long tid;
   tid = (long)t;

   Sleep(1000);
   cout <<"Sleeping in thread"<< endl;
   cout <<"Thread with id: " << tid << "exiting ...!" << endl;
   pthread_exit(NULL);
}

int main(){
    int rc,i;
    pthread_t theads[NUM_THREADS];
    pthread_attr_t attr;
    void *status;

    //初始化並設置線程爲可連接的(joinable)
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);

    for(i = 0; i < NUM_THREADS ; i ++){
        cout << "main() : creating thread: " << i <<endl;
        rc = pthread_create(&theads[i],NULL,wait,(void *)i);
        if(rc){
            cout << "Error:uable to create thread," << endl;
            exit(-1);
        }
    }

    //刪除屬性並等待其他線程
    pthread_attr_destroy(&attr);
    for(i = 0; i < NUM_THREADS; i ++){
        rc = pthread_join(theads[i],&status);
        if(rc){
            cout <<"Uable to join," << endl;
            exit(-1);
        }
        cout << "Main:completed thread id:" << i << endl;
        cout << "exiting with status :" << status << endl;
    }

    cout << "Main: program exiting." << endl;
    pthread_exit(NULL);
    return 0;
}
案例中先創建線程,然後設置線程的屬性爲joinable,最後回收線程,執行效果如下:

main() : creating thread: 0
main() : creating thread: 1
main() : creating thread: 2
main() : creating thread: 3
main() : creating thread: 4
Sleeping in thread
Thread with id: 1exiting ...!
Sleeping in thread
Thread with id: 3exiting ...!
Sleeping in thread
Thread with id: 0exiting ...!
Sleeping in thread
Thread with id: 2exiting ...!
Sleeping in thread
Thread with id: 4exiting ...!
Main:completed thread id:0
exiting with status :0
Main:completed thread id:1
exiting with status :0
Main:completed thread id:2
exiting with status :0
Main:completed thread id:3
exiting with status :0
Main:completed thread id:4
exiting with status :0
Main: program exiting.
三、移植環境搭建

大家可以注意到,上述的程序都是posix pthread接口即在Linux下使用的api,在win下默認是不能編譯通過,所以編譯之前我們需要做好移植工作,如下:

1.下載windows支持的posix pthread庫,路徑:點擊打開鏈接

2.解壓庫代碼:

解壓pthreads-w32-2-7-0-release .rar到D盤,庫路徑爲D:\Documents\pthreadlib\Pre-built.2\

3.在QT中指定庫的路徑:

LIBS += -LD:\Documents\pthreadlib\Pre-built.2\lib -lpthread




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章