gpt4 book ai didi

java - 需要有关 Java Vector/ConcurrentModificationException 同步的建议

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:52:48 25 4
gpt4 key购买 nike

在遗留应用程序中,我有一个 Vector,它保留要处理的文件的时间顺序列表,并且多个线程要求它处理下一个文件。 (请注意,我意识到可能有更好的集合可供使用(请随意提出建议),但我现在没有时间进行如此大的更改。)

在预定的时间间隔内,另一个线程会检查工作目录以查看是否有任何文件似乎因出现问题而被孤立。如果系统异常繁忙,此线程调用的方法偶尔会抛出 ConcurrentModificationException。所以我知道至少有两个线程正在尝试同时使用 Vector。

这是代码。我认为问题在于在返回的 Vector 上使用了 clone()。

private synchronized boolean isFileInDataStore( File fileToCheck ){
boolean inFile = false;
for( File wf : (Vector<File>)m_dataStore.getFileList().clone() ){
File zipName = new File( Tools.replaceFileExtension(fileToCheck.getAbsolutePath(), ZIP_EXTENSION) );
if(wf.getAbsolutePath().equals(zipName.getAbsolutePath()) ){
inFile = true;
break;
}
}
return inFile;
}

getFileList()方法如下:

public synchronized Vector<File> getFileList() {
synchronized(fileList){
return fileList;
}
}

作为快速修复,更改 getFileList 方法以返回 vector 的副本是否足够?

public synchronized Vector<File> getFileListCopy() {
synchronized(fileList){
return (Vector<File>)fileList.clone();
}
}

我必须承认,我通常对 Java 中 synchronized 的使用感到困惑,因为它与集合有关,因为简单地声明该方法是不够的。作为一个额外的问题,将方法声明为同步并用另一个同步块(synchronized block)包装返回调用只是疯狂编码吗?看起来多余。

编辑:这是接触列表的其他方法。

public synchronized boolean addFile(File aFile) {
boolean added = false;
synchronized(fileList){
if( !fileList.contains(aFile) ){
added = fileList.add(aFile);
}
}
notifyAll();
return added;
}

public synchronized void removeFile( File dirToImport, File aFile ) {
if(aFile!=null){
synchronized(fileList){
fileList.remove(aFile);
}
// Create a dummy list so I can synchronize it.
List<File> zipFiles = new ArrayList<File>();
synchronized(zipFiles){
// Populate with actual list
zipFiles = (List<File>)diodeTable.get(dirToImport);
if(zipFiles!=null){
zipFiles.remove(aFile);
// Repopulate list if the number falls below the number of importer threads.
if( zipFiles.size()<importerThreadCount ){
diodeTable.put(dirToImport, getFileList( dirToImport ));
}
}
}
notifyAll();
}
}

最佳答案

基本上,这里有两个独立的问题:sycnhronization 和 ConcurrentModificationException。 Vector 对比于例如ArrayList 在内部是同步的,因此像 add()get() 这样的基本操作不需要同步。但是,如果您迭代 Vector 并同时修改它,您甚至可以从单个线程获取 ConcurrentModificationException,例如通过插入一个元素。因此,如果您在 for 循环内执行修改操作,即使是单个线程也可能会破坏 Vector。现在,如果您在类之外返回您的 Vector,您不会阻止任何人在他们的代码中没有适当同步的情况下修改它。在 getFileList() 的原始版本中对 fileList 的同步是没有意义的。返回副本而不是原始副本可能会有所帮助,就像使用允许在迭代时进行修改的集合一样,例如 CopyOnWriteArrayList。 (但请注意修改的额外成本,在某些情况下它可能会成为阻碍)。

关于java - 需要有关 Java Vector/ConcurrentModificationException 同步的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9690033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com