Java 为什么我应该;“最后的”;多线程程序中的共享变量
我的问题是为什么我应该使用final来修饰变量list?它被匿名内部类的实例使用,没有final,它不会编译 代码如下所示:Java 为什么我应该;“最后的”;多线程程序中的共享变量,java,concurrency,Java,Concurrency,我的问题是为什么我应该使用final来修饰变量list?它被匿名内部类的实例使用,没有final,它不会编译 代码如下所示: public class TwoThreadsOneListCurrModi { public static void main(String[] args) { final List<String> list = Collections.synchronizedList(new ArrayList<String>());
public class TwoThreadsOneListCurrModi
{
public static void main(String[] args)
{
final List<String> list = Collections.synchronizedList(new ArrayList<String>());
for (int i =0 ; i<20;i++)
list.add(String.valueOf(i));
Thread t1 = new Thread(new Runnable(){
@Override
public void run()
{
synchronize(list) {
System.out.println("size of list:" +list.size());
}
}
});
t1.start();
}
}
公共类TwoThreadsOneListCurrModi
{
公共静态void main(字符串[]args)
{
最终列表=Collections.synchronizedList(新的ArrayList());
对于(int i=0;i这与多线程无关。之所以存在,是因为您试图从匿名内部类的方法访问list
。在这种情况下,Java将始终签署错误
在本例中,您正在使用new
关键字在此处创建Runnable
的匿名实例。您试图从run
取消引用的所有内容都必须是final
如果你对最后一个关键词的必要性感到好奇,你可以查阅Jon Skeet的文章,其中有详细的解释
关键是,当您创建匿名内部类的实例时,该类中使用的任何变量都会通过自动生成的构造函数将其值复制进来,如果该变量可以由该方法的其余部分修改,那么vica也可以修改,这看起来会很奇怪。您可能需要提及需要va的方法riable to final,关于Java在将变量交给匿名内部类之前创建变量的副本,等等。感谢您指出。如果它不是final,这将意味着类似闭包的行为,Java不支持。Java不支持它……但是。您在回答中的引用是错误的,几乎达到了城市传奇的状态在Java社区中。这与从堆栈中清除局部变量无关。Java对象是在堆上创建的,而不是在堆栈上创建的,原语只是传递的值。相反,这与Java中缺少闭包以及Java在将变量传递到匿名类之前需要复制变量有关。请阅读如果你要引用任何人的话,请引用他的话。事实上,让我们投票以重复的方式结束这个问题。
public class TwoThreadsOneListCurrModi2
{
public static void main(String[] args)
{
final List<String> list = Collections.synchronizedList(new ArrayList<String>());
initialize list;
Thread t1 = new WorkThread(list);
Thread t2 = new WorkThread(list);
t1.start();
t2.start();
}
}
class WorkThread extends Thread{
List<String> list;
public void run(){
do sth with list and synchronize block on list
}
Work1(List<String> list)
{ this.list = list; }
}