2016-07-16 40 views
3

我是新來的線程概念,我試圖更好地理解它們。在閱讀理論後,我決定用線程編寫一個簡單的程序。我在網上找到這個(也許很簡單):如何使此代碼中的線程獨立運行

編寫一個程序,計算不同線程上的Fibunacci 的素數和數字。

a。第一個線程開始從1開始搜索素數,直到 查殺該程序,並且當發現素數時,程序 必須顯示查找該數字的時間。

b。第二個線程是從1開始計算並打印Fibunacci 的數字,直到殺死程序。當一個新的Fibunacci號碼是 找到該程序打印此號碼和計算此 號碼的時間。

c。時間以毫秒爲單位(毫秒)

d。考慮沒有來自 控制檯的重疊消息的策略。

e。該計劃必須使用盡可能大的數字。當 號碼太大,無法保存類型如無符號long long 程序停止計算該類型的數字並顯示錯誤 消息。

示例輸出:

Prime 1,0.1ms。

Fibunacci 1,0.1ms。

總理2,0.1毫秒。

Fibunacci 2,0.1ms。

總理3,0.1毫秒。

Fibunacci 3,0.1ms。

Fibunacci 5,0.1ms。

Prime 5,0.1ms。

Fibunacci 8,0.1ms。

總理7,0.1毫秒。

Fibunacci 13,0.2ms。

Fibbunaci 21,0.1ms。

總理11,0.2ms。

這是我寫的代碼:

#include <iostream> // std::cout 
#include <string> // std::cout << std::string 
#include <thread> // std::thread 
#include <time.h> // clock() 
#include <mutex> // std::mutex 

std::mutex mtx; 
int timePrim, timeFib; 

bool isPrime(int testedNumber) 
{ 
    if (testedNumber <= 2) return true; 
    if (testedNumber % 2 == 0) return false; 
    for (int i = 3; (i*i) <= testedNumber; i += 2) 
    { 
     if (testedNumber % i == 0) return false; 
    } 
    return true; 
} 

// the function is realized by a recursive algorithm; credits to stackoverflow ;) 
bool isFibonacci(unsigned long long testedNumber, int a = 1, int b = 1) 
{ 
    if (testedNumber == 0 || testedNumber == 1) 
     return true;//returning true for 0 and 1 right away. 
    int nextFib = a + b;//getting the next number in the sequence 
    if (nextFib > testedNumber) 
     return false;//if we have passed the tested number, it's not in the sequence 
    else if (nextFib == testedNumber) 
     return true;//if we have a perfect match, the tested number is in the sequence 
    else 
     isFibonacci(testedNumber, b, nextFib);//otherwise, get the next fibonacci number and repeat. 
} 

void CheckNumber(unsigned long long numberToCheck, bool ifPrime) 
{ 
    bool result = false; 
    if (ifPrime == true) 
    { 
     result = isPrime(numberToCheck); 
    } 
    else 
    { 
     result = isFibonacci(numberToCheck); 
    } 
    if (result == true) 
    { 
     float currentTime = 0; 
     std::string typeNumber = ""; 
     if (ifPrime == true) 
     { 
      typeNumber = "Prime"; 
      currentTime = (float)(clock() - timePrim)/CLOCKS_PER_SEC; 
      timePrim = clock(); 
     } 
     else 
     { 
      typeNumber = "Fibonacci"; 
      currentTime = (float)(clock() - timeFib)/CLOCKS_PER_SEC; 
      timeFib = clock(); 
     } 
     mtx.lock(); 
     std::cout << typeNumber << " number " << numberToCheck << "; time " << currentTime << std::endl; 
     mtx.unlock(); 
    } 
} 

int main() 
{ 
    timePrim = timeFib = clock(); 

    for (unsigned long long i = 0; true; i++) // endless for loop == while(true) // by requirements 
    { 
     std::thread primeThread = std::thread(CheckNumber, i, true); 
     std::thread fibThread = std::thread(CheckNumber, i, false); 
     primeThread.join(); 
     fibThread.join(); 
    } 

} 

據我瞭解,這兩個線程應該走獨立彼此和打印結果以最快的速度相關的功能找了一些。但是結果顯得很簡單 - 按照主函數中for循環中迭代器的前進順序,而不是計算時間。 這是來自控制檯的片段:

素數0;時間0.005

斐波納契數0;時間0.007

素數1;時間0.03

斐波納契數1;時間0.029

素數2;時間0.093

斐波納契數2;時間0.092

素數3;時間0.023

斐波納契數3;時間0.023

素數5;時間0.05

斐波納契數5;時間0.052

素數7;時間0.023

斐波那契數8;時間0.045

素數11;時間0.038

素數13;時間0.077

斐波納契數13;時間0.091

素數17;時間0.019

素數19;時間0.179

斐波納契數21;時間0.208

素數23;時間0.027

爲了使獨立線程運行,我應該在這段代碼中糾正什麼?我的錯在哪裏?

//對不起,如果上面的英文文本是壞的 - 這不是我的母語,因此有可能我已經犯了一些錯誤......

+0

你打算有多少個線程? 2,3還是無限的? – nwp

+0

join()等待線程完成,所以每次循環都被序列化 –

回答

1

現在你的程序爲每個數字i創建線程,所以如果你計算素數和fibonaccis i從0到gazilion,它將創建並銷燬2 gazilions線程。線程創建需要完成系統調用,並且在循環中這樣做並不是特別快。

此外,您在提交更多工作之前讓兩個線程都彼此等待。

這是你的程序的外觀如何在僞代碼(如與真正的編程語言,純屬巧合):

def prime(i): 
    calculate one prime 

def fibo(i): 
    calculate one fibo 

for i from 0 to gazilion: 
    prime_thread = create_and_run_thread(prime, i) # expensive, runs gazilion times 
    fibo_thread = create_and_run_thread(fibo, i) # expensive, runs gazilion times 

    wait_for(prime_thread)  # wait until single number is crunched 
    wait_for(fibo_thread)  # wait until single number is crunched 

    destroy_thread(prime_thread)     
    destroy_thread(fibo_thread)     

相反,你可以創建每個單獨的任務和環2個的永久主題:

def prime(): 
    for i from 0 to gazilion: 
     calculate one prime 

def fibo(): 
    for i from 0 to gazilion: 
     calculate one fibo 


prime_thread = create_and_run_thread(prime) # expensive, but runs only once 
fibo_thread = create_and_run_thread(fibo) # expensive, but runs only once 

wait_for(prime_thread)  # you only wait until gazilion is reached 
wait_for(fibo_thread)  # you only wait until gazilion is reached 

destroy_thread(prime_thread)     # runs oly once 
destroy_thread(fibo_thread)     # runs oly once 
1

創建std::thread對象的兩個向量。一個用於斐波納契計算,一個用於素數計算。然後有兩個循環:一個創建兩個線程並將它們添加到向量中,另一個循環之後加入向量中的所有線程。

第二個循環等待第一個線程退出時,第一個循環中創建的所有線程將並行運行。


你現在正在做的是創建兩個線程,然後立即等待它們結束,然後再次在循環中重複。這意味着一次只能運行一個Fibonacci和一個素數的線程。