有人可以向我解释以下行为吗? 鉴于此代码:
for(int j = 0; j<100; j+=10) {
for(int i = 0; i<10; i++) {
threads[i] = new Thread(new RunAmounts(i+j));
threads[i].start();
}
for(Thread thread : threads) {
try {
if(thread != null)
thread.join();
} catch(InterruptedException ie) {
ie.printStackTrace();
return;
}
}
System.gc();
}
假设 RunAmounts 除了打印其参数之外什么也不做。人们期望 0-99 的每个数字都打印一次,但每个数字最终都会打印多次。有人可以解释一下线程的这个属性吗?
编辑:可能是由于 run(),实际上,代码将唯一的 pageNum 传递给 RunAmounts,后者将其附加到 SQL 语句
class RunAmounts extends Thread {
private int pageNum;
public RunAmounts(int pageNum) {
this.pageNum = pageNum;
}
public void run() {
ResultSet rs = null;
String usdAmt, row[] = new String[5], extr[] = new String[3];
LinkedList<String[]> toWrite = new LinkedList<String[]>();
CSVWriter fw = null;
boolean cont;
try {
fw = new CSVWriter(new FileWriter("Amounts.csv", true), ',');
do {
//executes SQL command, initializes rs & pst
cont = pst.execute();
while(rs.next()) {
//does a bit of parsing
toWrite.addFirst(row);
synchronized(this) {
fw.writeAll(toWrite);
fw.flush();
}
toWrite.clear();
}
System.out.println("page: " + Integer.toString(pageNum));
rs.close();
} while(cont);
fw.close();
} catch(Exception e) {e.printStackTrace();}
}
最佳答案
这个例子对我来说很难阅读,需要仔细阅读才能看到它只在最近启动的 10 个线程上调用 join。该数组可以被删除(除非您想保留对它们的引用以便对它们调用中断,当然在这种情况下您需要更大的数组),Groovy 中的等效功能可以这样编写:
class RunAmounts implements Runnable {
final int i
public void run() {
println i
}
RunAmounts(int i) {this.i = i}
}
def foo() {
(0 .. 90).step(10).each { j ->
(0 .. 9).each { i ->
t = new Thread(new RunAmounts(i + j) as Runnable)
t.start()
t.join()
}
}
}
而且效果很好。我可以将数组部分添加回来(此处使用列表,但它是相同的概念)
def foo() {
(0 .. 90).step(10).each { j ->
threads = []
(0 .. 9).each { i ->
t = new Thread(new RunAmounts(i + j) as Runnable)
t.start()
threads << t
}
threads.each { it.join() }
}
}
而且它仍然有效。
所以我认为你找错地方了。要么您在创建此示例时删除了真正的问题,要么您的问题出在其他地方。
如何获取 RunAmounts 对象的数据库连接已从您的示例中进行了编辑。 JDBC 对象不是线程安全的(连接在技术上是线程安全的,尽管这对应用程序开发人员没有帮助,实际上它们的使用需要一次限制在一个线程中),如果您在这部分做错了,可能会一个问题。
关于Java 线程似乎运行多次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24640204/