本文主要是介绍Caused by: java.util.ConcurrentModificationException,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Caused by: java.util.ConcurrentModificationException
- 1. 关于 ConcurrentModificationException 报错
- 2. 报错日志
- 3. 代码逻辑`doInBackground`
- 4. 修改方案
- 5. 方案解析
1. 关于 ConcurrentModificationException 报错
在 Java 中,当尝试在迭代过程中修改对象的结构时,就会发生此错误Caused by: java.util.ConcurrentModificationException
。发生这种情况的原因是迭代器根据集合的结构维护内部状态,迭代过程中对集合的任何修改都会破坏此状态,从而导致异常。
2. 报错日志
05-01 23:47:48.162 10807 10963 E AndroidRuntime: FATAL EXCEPTION: pool-12-thread-1
05-01 23:47:48.162 10807 10963 E AndroidRuntime: Process: com.xxx.filemanager, PID: 10807
05-01 23:47:48.162 10807 10963 E AndroidRuntime: java.lang.RuntimeException: An error occurred while executing doInBackground()
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at android.os.AsyncTask$4.done(AsyncTask.java:415)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:381)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.concurrent.FutureTask.setException(FutureTask.java:250)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.concurrent.FutureTask.run(FutureTask.java:269)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.lang.Thread.run(Thread.java:1023)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: Caused by: java.util.ConcurrentModificationException
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.ArrayList$Itr.next(ArrayList.java:860)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at com.xxx.filemanager.fragment.FileExplorerViewFragment$LoadlistDataTask.doInBackground(FileExplorerViewFragment.java:912)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at com.xxx.filemanager.fragment.FileExplorerViewFragment$LoadlistDataTask.doInBackground(FileExplorerViewFragment.java:861)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at android.os.AsyncTask$3.call(AsyncTask.java:394)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: at java.util.concurrent.FutureTask.run(FutureTask.java:264)
05-01 23:47:48.162 10807 10963 E AndroidRuntime: ... 3 more
3. 代码逻辑doInBackground
@Override
protected ArrayList<FileInfo> doInBackground(Void... params) {ArrayList<FileInfo> fileLists = new ArrayList<>();ArrayList<FileInfo> mCheckedFileNameList = mFileViewInteractionHub.getSelectedFileList();for (FileInfo f : mCheckedFileNameList) {//遍历逻辑}
}
在后台任务执行时,进行了其他的操作修改了mFileViewInteractionHub.getSelectedFileList()
值,导致的ConcurrentModificationException
报错。
4. 修改方案
@Override
protected ArrayList<FileInfo> doInBackground(Void... params) {ArrayList<FileInfo> fileLists = new ArrayList<>();
- ArrayList<FileInfo> mCheckedFileNameList = mFileViewInteractionHub.getSelectedFileList();
+ ArrayList<FileInfo> mCheckedFileNameList = new ArrayList<FileInfo>(mFileViewInteractionHub.getSelectedFileList());for (FileInfo f : mCheckedFileNameList) {//遍历逻辑}
}
5. 方案解析
=
赋值是属于共享相同的实例,addAll
是独立的实例。这两种方式在功能上是相似的,但存在一些微小的区别。
方式一:
ArrayList<FileInfo> mCheckedFileNameList = mFileViewInteractionHub.getSelectedFileList();
这种方式直接将 mCheckedFileNameList
引用指向 mFileViewInteractionHub.getSelectedFileList()
返回的列表对象。这意味着 mCheckedFileNameList
和 mFileViewInteractionHub.getSelectedFileList()
引用的是同一个列表对象,它们共享相同的实例。因此,对 mCheckedFileNameList
的修改会直接反映在 mFileViewInteractionHub.getSelectedFileList()
返回的列表上,反之亦然。
方式二:
ArrayList<FileInfo> mCheckedFileNameList = new ArrayList<FileInfo>();
mCheckedFileNameList.addAll(mFileViewInteractionHub.getSelectedFileList());
这种方式创建了一个新的 ArrayList
对象,并通过 addAll
方法将 mFileViewInteractionHub.getSelectedFileList()
返回的列表中的所有元素添加到新创建的列表中。此时,mCheckedFileNameList
和 mFileViewInteractionHub.getSelectedFileList()
引用的是不同的列表对象,它们各自拥有独立的实例。因此,对 mCheckedFileNameList
的修改不会影响 mFileViewInteractionHub.getSelectedFileList()
返回的列表,反之亦然。
在使用这两种方式时,您可以根据具体需求选择适合的方式。如果您希望在修改 mCheckedFileNameList
的同时影响原始列表,可以使用方式一。如果您希望在修改 mCheckedFileNameList
时不影响原始列表,可以使用方式二。
请注意,这些区别仅适用于列表对象本身的修改。如果列表中的元素是可变对象,并且在 mCheckedFileNameList
和 mFileViewInteractionHub.getSelectedFileList()
之间共享相同的元素实例,则无论使用哪种方式,对元素的修改都将在两个列表中反映出来。
这篇关于Caused by: java.util.ConcurrentModificationException的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!