有人可以向我解释以下行为吗? 鉴于此代码:
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();}
}
答案 0 :(得分:0)
如果删除第一个内部循环,
,您的断言将是有效的Thread[] threads = new Thread[100];
for(int j = 0; j<threads.length; j++) {
//for(int i = 0; i<10; i++) {
threads[j] = new Thread(new RunAmounts(j));
threads[j].start();
// }
}
for(Thread thread : threads) {
try {
if(thread != null)
thread.join();
} catch(InterruptedException ie) {
ie.printStackTrace();
return;
}
}
}
答案 1 :(得分:0)
这个例子对我来说很难阅读,需要仔细阅读才能看到它只在最近启动的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对象不是线程安全的(连接在技术上是线程安全的,但是对应用程序开发人员没有帮助,实际上他们的使用需要一次只限于一个线程),如果你做这个部分这可能是一个问题。
答案 2 :(得分:0)
如果您阅读本手册,您会发现我告诉您第3行可能存在添加问题。
尽管
/* thread 1 */
t1 = new Date().getTime();
/* thread 2 */
t2 = new Date().getTime();
if(t2 < t1){
System.out.println("Your wrong with your assumption");
}
如果精度不会出现问题,那么它是不合适的。
docs.oracle.com/javase/specs/jls/se7/html/jls-17.html
使用原子操作以确保内存障碍。
我告诉你的原因并不重要。
你对时间的假设可能是错误的:
t2-t1&gt; 0
答案 3 :(得分:0)
我对时间做了一些想法,并且有一个以上的变量听起来像疯了。你的问题是计算和同步的基础。
我希望您参考我撰写的博客文章: http://sourceforge.net/p/ags/blog/2014/07/mathematical-properties-of-timing/
我在我的系统上进行线程同步,它确实不可靠并且意外崩溃即将到期。