在内部类中绕过“最终或有效最终”会产生非常随机的结果

时间:2014-11-25 11:56:13

标签: java lambda parallel-processing

我正在为一个400行矩阵的矩阵乘法做一个编程类项目。我让它以顺序模式工作,该项目的目标是编写并行实现。

我有以下代码,当然当我尝试在内部类中引用计数器j时,我得到一个关于j必须如何“最终或有效最终”的错误。我发现这个解决方法是使用最后一个数组,但更改了第一个元素,但它给出了非常不可预测的结果,我原本预计这会从0到399计算,但它会以随机顺序吐出数字,然后复制很多数字,包括399很多次。

我是如何在内部类中使用递增计数器的?目标是调用方法来处理内部类中矩阵中每一行的矩阵乘法,因为我们应该有与矩阵中的行一样多的线程。谢谢你的帮助!

以下是代码:

private static double parallelMatrixMultiply()
{
    // use the existing arrays A and B, multiply them together
    // use the parallel approach
    // Create a fixed thread pool with maximum of three threads
    ExecutorService executor = Executors.newFixedThreadPool(numRows);

    final int[] counter = new int[]{0};

    // submit a new thread for each row in the matrix
    for (int j = 0; j < numRows ; j++)
    {
        // we can modify an element of an array that has been declared final
        counter[0] = j;
        // Submit runnable tasks to the executor
        executor.execute(new Runnable() {
            public void run() 
            {
                // set a task to multiply for each row here
                // will be replaced by a line to multiply each row of matrix
                System.out.println(counter[0]);
            }
        });
    }

    // Shut down the executor
    executor.shutdown();

    // return the value of the 1,1 position on zero notation
    //return matrixC.get(1).get(1); // return matrixC(1,1)
    return 42.0;
}

1 个答案:

答案 0 :(得分:3)

counter是您可以在回调方法中使用的最终变量。但是数组的内容不是最终的,你不断改变它们。调用run()方法时,它会查看当时正在持有counter[0] ,而不是在您调用execute时的循环中。

你最好这样做:

for (int j = 0; j < numRows ; j++) {
    final int finalj = j;
    executor.execute(new Runnable() {
        public void run() {
            System.out.println(finalj);
        }
    });
}

也就是说,将循环计数器的值赋给实际上是最终的变量,以供回调方法使用。