我在求职面试中发现了这个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];
}
答案 0 :(得分:4)
此代码存在几个主要问题,这里有一些:
start()
方法。c[0]
中的值。为此,必须在创建的每个线程上调用join()
方法。c[0]
不是线程安全的。这些数据由多个线程同时访问,需要保护某种锁定机制。s0
和s1
都是0
,在进一步的迭代中,s1
比s2
提前一个。不知道算法究竟想要什么,这可能是也可能不正确,但看起来很可疑。此外,还有一些奇怪的事情:
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();
}