我有时会从以下代码中得到以下异常 人们建议,如果我将 for 循环设置为迭代器,它将解决该问题。但我不明白如果我没有删除 for 循环内的任何元素而是调用 pendingActions.clear(); 之后。如果有人遇到过这种情况,请告诉我。另外,你认为我是否向
private List<Action> pendingActions = Collections.synchronizedList(new ArrayList<>());
Run Code Online (Sandbox Code Playgroud)
会解决问题吗?
private List<Action> pendingActions = new ArrayList<>();
private void runPendingNavigationActions() {
if (!pendingActions.isEmpty()) {
for (Action r : pendingActions) {
r.run();
}
pendingActions.clear();
}
}
Run Code Online (Sandbox Code Playgroud)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4156)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at com.app.android.view.fragment.MainFragment.runPendingNavigationActions(MainFragment.java:1355)
Run Code Online (Sandbox Code Playgroud)
您使用了错误的数据结构: aQueue
将是更好的选择,特别是为并发修改而设计的。
例如,您可以使用LinkedBlockingQueue
. 您可以像列表一样添加到它,然后使用添加的操作,例如:
Action r;
while ((r = queue.poll()) != null) {
r.run();
}
Run Code Online (Sandbox Code Playgroud)
使用Collections.synchronizedList
不会解决您的问题,至少本身不会。
使用包装列表要记住的事情Collections.synchronizedList()
是它只为每个单独的方法调用提供互斥,例如,直到调用pendingActions.get()
或pendingActions.iterator()
返回。
增强的 for 循环隐式地创建了一个Iterator
; 但是当您迭代它时,该列表不会被锁定,无论这是否来自同步列表。
您的另一个线程在此迭代期间正在更改列表,并且在ConcurrentModificationException
您下次尝试从迭代器获取值时仍会导致此问题。
现在,你可以把它的工作(不CME)通过在包装迭代synchronized
块,以及:
synchronized (pendingActions) {
for (Action r : pendingActions) {
r.run();
}
r.clear();
}
Run Code Online (Sandbox Code Playgroud)
这样做的问题是,在迭代列表时,其他线程现在将被阻塞。这可能会导致您的应用程序出现明显延迟;也可能不会,这取决于调用此方法的频率以及操作运行所需的时间。
然而,使用并发队列完全避免了这个问题,并且可能比同步列表更快,因为非阻塞并发队列不需要使用“全面”同步。
归档时间: |
|
查看次数: |
3402 次 |
最近记录: |