我正在学习Java中的Threading,以便创建一些并行运行的程序。设计具有并行性的程序是我从未有机会在我的学校编程课上学习的东西。我知道如何创建线程并让它们运行,但我不知道如何有效地使用它们。毕竟我知道它实际上并没有使用线程来使程序快速但是很好的并行设计。所以我做了一些实验来测试我的知识。但是,我的并行版本实际上比无与伦比的版本慢。我开始怀疑自己是否真的明白了。如果你可以这么善良,你介意看看下面的程序:
我制作了一个以分而治之的方式填充数组的程序(我知道Java有一个Arrays.fill实用程序,但我只想测试我在多线程中的知识):
public class ParalledFill
{
private static fill(final double [] array,
final double value,
final int start,
final int size)
{
if (size > 1000)
{ // Each thread handles at most 1000 elements
Runnable task = new Runnable() { // Fork the task
public void run() {
fill(array, value, start, 1000); // Fill the first 1000 elements
}};
// Create the thread
Thread fork = new Thread(task);
fork.start();
// Fill the rest of the array
fill(array, value, start+1000, size-1000);
// Join the task
try {
fork.join();
}
catch (InterruptedException except)
{
System.err.println(except);
}
}
else
{ // The array is small enough, fill it via a normal loop
for (int i = start; i < size; ++i)
array[i] = value;
}
} // fill
public static void main(String [] args)
{
double [] bigArray = new double[1000*1000];
double value = 3;
fill(bigArray, value, 0, bigArray.length);
}
}
我测试了这个程序,但事实证明它甚至比仅执行以下操作更慢:
for (int i = 0; i < bigArray.length; ++i)
bigArray[i] = value;
我猜测,可能是java使用循环来填充数组进行了一些优化,这使得它比我的线程版本快得多。但除此之外,我更强烈地感觉到我处理线程/并行的方式可能是错误的。我从来没有使用线程设计任何东西(总是依赖编译器优化或C中的OpenMP)。任何人都可以帮我解释为什么我的并行版本不会更快?在设计并行程序方面该程序是否太糟糕了?
谢谢, 性。
答案 0 :(得分:0)
除非您有多个CPU或I / O等长时间运行的任务,否则我猜你所做的就是在线程之间切换时间。如果有一个CPU需要做很多工作,那么添加线程并不会减少必须完成的工作。所有你最终都会因为上下文切换而增加开销。
您应该阅读“Java Concurrency In Practice”。更好地学习如何使用现代并发包而不是原始线程来做事。