1

我正在学习 Java 中的线程,以便创建一些并行运行的程序。设计具有并行性的程序是我在学校编程课上从未有机会学习的东西。我知道如何创建线程并使它们运行,但我不知道如何有效地使用它们。毕竟我知道实际上并不是使用线程来使程序快速运行,而是一种良好的并行设计。所以我做了一些实验来测试我的知识。但是,我的并行版本实际上比无与伦比的版本运行得慢。我开始怀疑我是否真的明白这个想法。如果你能这么好,你介意看看我的以下程序:

我编写了一个程序以分而治之的方式填充数组(我知道 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)。谁能帮我解释为什么我的并行版本不快?该程序在设计并行程序方面是否太糟糕了?

谢谢,邢。

4

1 回答 1

0

除非你有多个 CPU,或者像 I/O 这样长时间运行的任务,否则我猜你所做的只是线程之间的时间切片。如果有一个 CPU 有很多工作要做,那么添加线程并不会减少必须完成的工作。您最终所做的只是由于上下文切换而增加了开销。

您应该阅读“Java 并发实践”。最好学习如何使用现代并发包而不是原始线程来做事。

于 2013-11-01T20:42:43.473 回答