Multithreading HashSet中的ConcurrentModificationException

Multithreading HashSet中的ConcurrentModificationException,multithreading,hashmap,hashset,concurrentmodification,Multithreading,Hashmap,Hashset,Concurrentmodification,我的代码如下,我得到ConcurrentModificationException,特别是在(字符串文件:files)行中 在执行迭代时,我不会更改“文件”的任何内容,所以为什么会导致异常,我应该如何避免它?谢谢你的建议 int getTotalLength(final HashSet<String> files) { int total = 0; int len; for (String file : files) {

我的代码如下,我得到ConcurrentModificationException,特别是在(字符串文件:files)行中

在执行迭代时,我不会更改“文件”的任何内容,所以为什么会导致异常,我应该如何避免它?谢谢你的建议

int getTotalLength(final HashSet<String> files) {
        int total = 0;
        int len;
        for (String file : files) {
            len = getLength(file);
            if (len != Long.MIN_VALUE) {
                total += len;
            }
        }
        return total;
    }




      int getLength(String file) {
        int len = Long.MIN_VALUE;

        if (file == null) {
            return len;
        }

        File f = new File(file);

        if (f.exists() && f.isFile()) {
            len = f.length();
        }

        return size;
    }
int getTotalLength(最终哈希集文件){
int-total=0;
内伦;
用于(字符串文件:文件){
len=getLength(文件);
if(len!=Long.MIN_值){
总+=len;
}
}
返回总数;
}
int getLength(字符串文件){
int len=Long.MIN_值;
if(file==null){
回程透镜;
}
文件f=新文件(文件);
如果(f.exists()&&f.isFile()){
len=f.长度();
}
返回大小;
}

参考您的注释,声明
最终哈希集文件
使变量
文件
最终-这意味着您不能在该变量的作用域内为该变量分配另一个对象
HashSet
本身是可变对象,可以修改-它与final修饰符无关(对set对象的引用itselt仍然相同)。 如果您想同时处理同一对象(同一哈希集),请使用
synchronized
块或方法


一般来说,对于每个类似的变量,您不能修改在
循环中使用
for
迭代的集合(在同一个线程或另一个线程中)。

参考您的注释,声明
final HashSet files
将使变量
files
成为final-这意味着您不能在该变量的作用域中将另一个对象分配给该变量
HashSet
本身是可变对象,可以修改-它与final修饰符无关(对set对象的引用itselt仍然相同)。 如果您想同时处理同一对象(同一哈希集),请使用
synchronized
块或方法


一般来说,你不能修改集合(在同一个线程或另一个线程中),对于每个类似的变量,你都可以在
中循环

那么你有没有其他线程可以同时修改集合?是的,这是可能的,但我已经将哈希集设置为最终。。。它不会阻止对集合进行修改吗?ConcurrentModification在您的HashSet上,而不是在您的HashSet上file@GreenHo:否,您已将变量
设置为final
。这与变量值引用的对象是否可以修改无关。@JonSkeet这种混淆是我渴望Java中的
const
的一大原因,更不用说它将消除对Guava的
不可变*
类的需要-您是否有其他线程可能同时修改该集?是的,这是可能的,但我已将哈希集设置为最终。。。它不会阻止对集合进行修改吗?ConcurrentModification在您的HashSet上,而不是在您的HashSet上file@GreenHo:否,您已将变量
设置为final
。这与变量值引用的对象是否可以修改无关。@JonSkeet这种混淆是我渴望Java中的
const
的一大原因,更不用说它将消除对Guava的
不可变*
类的需要-d调用getTotalLength()的调用者(比如callerA)是一个已同步的方法,调用者不修改集合,但调用callerA的callerB修改集合。。。代码如下所示:void callerB(){modify the HashSet;callerA();}void callerA(){calls getTotalLength(),其中我得到了异常}我应该在调用者B中使用synchronized块,以便void callerB(){synchronized(HashSet){修改HashSet;callerA()迭代HashSet;}如果该方法(正如您所提到的“synchronized method”)是同步的,这意味着如果一个线程正在执行该方法(在该方法的“内部”),则在上一次执行结束之前,不允许另一个线程执行该方法。如果您同步了两个不同的方法(在方法签名中使用
synchronized
关键字),则它们不会彼此同步。必须将公共对象上的代码显式同步到要同步的两个方法。调用getTotalLength()的调用方(例如callerA)是一个已同步的方法,调用方不修改集合,但调用callerA的callerB修改集合。。。代码如下所示:void callerB(){modify the HashSet;callerA();}void callerA(){calls getTotalLength(),其中我得到了异常}我应该在调用者B中使用synchronized块,以便void callerB(){synchronized(HashSet){修改HashSet;callerA()迭代HashSet;}如果该方法(正如您所提到的“synchronized method”)是同步的,这意味着如果一个线程正在执行该方法(在该方法的“内部”),则在上一次执行结束之前,不允许另一个线程执行该方法。如果您同步了两个不同的方法(在方法签名中使用
synchronized
关键字),则它们不会彼此同步。必须将公共对象上的代码显式同步到要同步的两个方法。