我尝试在10个线程并发Java线程上运行从一个到上限函数的简单求和。我当前的主要问题是为upperBound,lowerBound,sum和i设置变量。我想捕获i变量更新总和计算,但我得到错误"局部变量需要被声明为final。"我是Java的初学者,但是从我读过的关于声明变量final的内容来看,它是保持变量不可修改的 - 而不是我的目标......正确吗?
public class threads {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
for(int i = 0; i < 10; i++) {
new Thread("" + i) {
public void run() {
int sum = 0;
int upperBound = 22;
int lowerBound = 1;
long threadID = Thread.currentThread().getId();
for (int number = lowerBound; number <= upperBound; number++){
sum = sum + number + i;
}
System.out.println("Thread: " + threadID + " is running now and will compute the sum from 1 to " + (upperBound + i));
System.out.println("Thread id " + threadID + " computes sum " + sum);
}
}.start();
}
}
}
答案 0 :(得分:0)
是的,声明i
变量final以便您可以在匿名Thread子类中使用它将阻止您修改它。但你可以用i的当前值创建另一个变量并做出最终结果:
for (int i = 0; i < 10; i++) {
final int iCopy = i;
/* use iCopy in the Thread subclass */
}
当然,如果你需要在内部类体中有一个可变的iCopy(在这种情况下你不是,但一般情况下你可能),你必须制作一个(非最终的)副本在班上iCopy
。
这可能看起来很烦人,但是Java试图在这里帮助你:如果你可以在另一个线程中使用i
,它应该看到i
的值 - 实例化内部类时的值(隐式副本),或者线程实际运行时的值(循环结束后为10)?许多带闭包的语言选择后者的解释。 Java设计者决定只让你在内部类(和lambdas)中使用最终变量来防止混淆,内部类只有一个值。
答案 1 :(得分:0)
您在public void run(){...}
方法中访问的变量应该声明为final
,作为java创建的安全措施。在为一个变量赋值后,不能重新赋值。您还可以在GLOBAL
方法中使用run
变量(推荐),因为它可以在run方法中再次重新赋值。在您的情况下,变量i
必须全局声明或声明为最终变量,或者在每个循环中任何其他最终变量应等于i
。您的工作代码将是: -
for(int i = 0; i < 10; i++) {
final int FINAL_I = i;
new Thread("" + FINAL_I) {
public void run() {
int sum = 0;
int upperBound = 22;
int lowerBound = 1;
long threadID = Thread.currentThread().getId();
for (int number = lowerBound; number <= upperBound; number++){
sum = sum + number + FINAL_I;
}
System.out.println("Thread: " + threadID + " is running now and will compute the sum from 1 to " + (upperBound + FINAL_I));
System.out.println("Thread id " + threadID + " computes sum " + sum);
}
}.start();
}
}
您也可以使用: -
for(int i = 0; i < 10; i++) {
new Thread("" + i) {
int i = this.i;
public void run() {
int sum = 0;
int upperBound = 22;
int lowerBound = 1;
long threadID = Thread.currentThread().getId();
for (int number = lowerBound; number <= upperBound; number++){
sum = sum + number + i;
}
System.out.println("Thread: " + threadID + " is running now and will compute the sum from 1 to " + (upperBound + i));
System.out.println("Thread id " + threadID + " computes sum " + sum);
}
}.start();
}
}