你能帮我弄清楚这个 Snipped of Java-code 应该做什么吗?
Can you help me figuring out, what this Snipped of Java-code is supposed to do?
我在求职面试问题中找到了这段 Java 代码,并试图弄明白。 (我是一个 Smalltalker,可能不像我想的那样熟悉 Java 的语法)。
据我所知,它为数据矩阵中的每一行生成一个线程。该线程似乎成对处理行向量中的每一列。它检查对中的第一项是否大于第二项。如果为真,它会增加一个全局计数器(?)并对数据做一些我不明白的事情(What's "or" defined to do with integers in 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];
}
这段代码有几个主要问题,这里有几个:
- 线程已创建,但从未启动。这意味着它们包含的代码将 永远不会 运行。为此,必须在创建的每个线程上调用
start()
方法。
- 线程不是 "joined" 最后,因此该方法将 return 在线程有机会执行计算之前
c[0]
中的值。为此,必须在创建的每个线程上调用 join()
方法。
- 线程对
c[0]
的更新不是线程安全的。该数据由多个线程并发访问,需要某种类型的锁定机制进行保护。
- 在内循环的第一次迭代中,
s0
和s1
都是0
,在进一步的迭代中,s1
比[=21早一个=].不知道算法实际想要什么,这可能正确也可能不正确,但看起来很可疑。
此外,还有一些奇怪的事情:
- 为什么要声明一个对象的单元素数组
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();
}
我在求职面试问题中找到了这段 Java 代码,并试图弄明白。 (我是一个 Smalltalker,可能不像我想的那样熟悉 Java 的语法)。
据我所知,它为数据矩阵中的每一行生成一个线程。该线程似乎成对处理行向量中的每一列。它检查对中的第一项是否大于第二项。如果为真,它会增加一个全局计数器(?)并对数据做一些我不明白的事情(What's "or" defined to do with integers in 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];
}
这段代码有几个主要问题,这里有几个:
- 线程已创建,但从未启动。这意味着它们包含的代码将 永远不会 运行。为此,必须在创建的每个线程上调用
start()
方法。 - 线程不是 "joined" 最后,因此该方法将 return 在线程有机会执行计算之前
c[0]
中的值。为此,必须在创建的每个线程上调用join()
方法。 - 线程对
c[0]
的更新不是线程安全的。该数据由多个线程并发访问,需要某种类型的锁定机制进行保护。 - 在内循环的第一次迭代中,
s0
和s1
都是0
,在进一步的迭代中,s1
比[=21早一个=].不知道算法实际想要什么,这可能正确也可能不正确,但看起来很可疑。
此外,还有一些奇怪的事情:
- 为什么要声明一个对象的单元素数组
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();
}