我是线程概念的新手,我试着更好地理解它们。在阅读了理论之后,我决定用线程编写一个简单的程序。我在互联网上找到了这个(也许是简单的)任务:
编写一个计算素数和Fibunacci数的程序 在不同的线程上。
一个。第一个线程开始从1开始搜索素数,直到 杀死程序并在程序中找到素数时 必须提供找到这个号码的时间。
湾第二个线程是计算和打印Fibunacci的数量 从1到杀死该程序。当新的Fibunacci数量 发现该程序打印此编号和计算时间 号。
℃。时间以毫秒(毫秒)显示
d。想想没有重叠消息的策略 控制台。
即该程序必须使用尽可能大的数字。当。。。的时候 数字太大,无法保持类型,如unsigned long long 程序停止计算那种数字并显示错误 消息。
示例输出:
Prime 1,0.1 ms。
Fibunacci 1,0.1 ms。
Prime 2,0.1 ms。
Fibunacci 2,0.1 ms。
Prime 3,0.1 ms。
Fibunacci 3,0.1 ms。
Fibunacci 5,0.1 ms。
Prime 5,0.1 ms。
Fibunacci 8,0.1 ms。
Prime 7,0.1 ms。
Fibunacci 13,0.2 ms。
Fibbunaci 21,0.1 ms。
Prime 11,0.2 ms。
这是我写的代码:
#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
Fibonacci数字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 :(得分:1)
创建两个std::thread
个对象的向量。一个用于斐波纳契计算,一个用于素数计算。然后有两个循环:一个用于创建两个线程并将它们添加到向量中,另一个循环用于连接向量中的所有线程。
当第二个循环等待第一个线程退出时,第一个循环中创建的所有线程都将以并行方式运行。
你现在正在做的是创建两个线程,然后立即等待它们再次在循环中迭代之前结束。这意味着一次只能运行一个Fibonacci和一个素数线程。
答案 1 :(得分:1)
现在你的程序为每个数字i
创建线程,所以如果计算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