你能帮我弄清楚,这个Java代码片段应该做什么?

时间:2015-02-22 15:17:57

标签: java matrix adjacency-matrix

我在求职面试中发现了这个Java代码并试图弄明白。 (我是一个Smalltalker,并且不像我想的那样熟悉Java的语法)。

据我所知,它为数据矩阵中的每一行产生一个线程。线程似乎成对处理行向量中的每一列。它检查对中的第一项是否大于第二项。如果为true,它会增加一个全局计数器(?)并对数据做一些事情,我不明白(什么"或"定义与Java中的整数有关?)。

我相信它也在某种程度上被打破了。你能帮我解决一下吗?我想了解发生了什么。

public static int process(int [][] data) {
    final Object[] c = new Object[]{0};
    Object[] p = new Object[data.length];
    for (int i = 0; i < p.length; i++) {
        final int [] r = data[i];
        p[i] = new Thread() {
            public void run() {
                for (int s0 = 0, s1 = 0; s0 < r.length - 1; s0++, s1 = s0 + 1) {
                    if (r[s0] > r[s1]) {
                        // what is this next line supposed to do?
                        r[s0] ^= r[s1]; r[s1] ^= r[s0]; r[s0] ^= r[s1];
                        // does this next line increase a global counter?
                        c[0] = ((Integer) c[0]) + 1;
                    }
                }
            }
        };
    }
    return (Integer) c[0];
}

1 个答案:

答案 0 :(得分:4)

此代码存在几个主要问题,这里有一些:

  • 线程已创建,但从未启动过。这意味着它们包含的代码永远不会运行。为此,必须在创建的每个线程上调用start()方法。
  • 线程未在末尾“连接”,因此该方法将在线程有机会执行计算之前返回c[0]中的值。为此,必须在创建的每个线程上调用join()方法。
  • 线程更新c[0]不是线程安全的。这些数据由多个线程同时访问,需要保护某种锁定机制。
  • 在内部for循环的第一次迭代中,s0s1都是0,在进一步的迭代中,s1s2提前一个。不知道算法究竟想要什么,这可能是也可能不正确,但看起来很可疑。

此外,还有一些奇怪的事情:

  • 为什么声明对象的单个元素数组c,因为它只有一个元素,并且永远不会用作数组,而是用作简单变量。我们可能想在这里使用AtomicInteger。这也将解决并发访问问题,因为AtomicInteger提供了线程安全性。
  • 没有输入任何内容。例如,数组p应该是Thread个对象的数组:

    Thread p[] = new Thread[data.length];
    

    同样,c的类型应为Integer[](或AtomicInteger

我已注释下面的代码:

// Method declaration, takes a two-demensional array of integers
public static int process(int [][] data) {
    // Create a one-demensional array of Objects, containing 
    // a single element, `0`.  This will be "auto-boxed" from
    // a primitive int to an Integer object.
    final Object[] c = new Object[]{0};
    // Create a one dimensional array of Objects, of the same
    // size as the first dimension of data
    Object[] p = new Object[data.length];

    // Loop through each index of the array p, declared above
    for (int i = 0; i < p.length; i++) {
        // get a reference, r, to the ith "row" of data
        final int [] r = data[i];
        // create a new Thread, and store a reference to it in p[i]
        p[i] = new Thread() {
            // This is the method that will be invoked on a separate
            // thread of execution by the java virtual machine
            public void run() {
                for (int s0 = 0, s1 = 0; s0 < r.length - 1; s0++, s1 = s0 + 1) {
                    if (r[s0] > r[s1]) {
                        // perform an xor-swap of two elements in the
                        // array (as pointed out by Jongware)
                        r[s0] ^= r[s1]; r[s1] ^= r[s0]; r[s0] ^= r[s1];
                        // this access of c[0] is not thread-safe
                        c[0] = ((Integer) c[0]) + 1;
                    }
                }
            }
        };
    }
    // return the value in c[0]
    return (Integer) c[0];
}

这是一个版本,我修复了上面提到的所有内容:

public static int process(int [][] data) {
    final AtomicInteger c = new AtomicInteger();
    Thread[] threads = new Thread[data.length];
    for (int i = 0; i < data.length; i++) {
        final int [] row = data[i];
        threads[i] = new Thread() {
            public void run() {
                for (int s0 = 0, s1 = 1; s0 < row.length - 1; s0++, s1 = s0 + 1) {
                    if (row[s0] > row[s1]) {
                        row[s0] ^= row[s1]; row[s1] ^= row[s0]; row[s0] ^= row[s1];
                        c.incrementAndGet();
                    }
                }
            }
        };
        threads[i].start();
    }
    try {
        for (Thread thread : threads)
            thread.join();
    } catch (InterruptedException e) {}
    return c.intValue();
}