Android中workerthread与UIthread同时访问同一资源造成ConcurrentModificationException解决参考
2014-08-21 16:35
447 查看
个人总结,若有问题,希望大家不吝指教,在此感谢。
项目中遇到一个ConcurrentModificationException异常,这种异常比较蛋疼,一般两个线程同时访问一个资源造成的,一个再改,一个再做别的,然后就不同步了。
Log数据中只给出一个点,不方便查询另一个问题点。这类必须解决的就是两个线程对同一个资源(我们这是一个HashMap)同步的问题,一个方式就是加锁解决,这是一个总方针。但是加锁如果加不好,就会造成UIthread的线程因为在锁那里等的时间比较长而造成ANR,当然这种情况不常见,因为你的超过5秒才能ANR,但是是有这个可能的,我们遇到了……
然后就是思考了两个方案,一个是做一个高优先级的线程(参考android线程优先级就能知道哪个合适,有俩都可以)来对UIthread里面对资源的访问提出来,这样不会ANR,但是项目大,地方多,这么干结构都得变,还有就是那种特别需要及时相应的地方(UI界面上的滑动动画啥的),担心这么做会有一定的延时。然后就放弃了,改动貌似有点大。
第二个方案就是做备份了,那备份给UIthread去使用。何时做、咋做备份又是个问题。然后就各种参考,这里不得不说,Android源码还是很碉堡的,最起码比我见过的一些大一点的项目代码要好。
给出一段代码,下面一段代码是桌面源码launcherModle里面的一段代码。
代码中sBgWorkspaceItems、sBgAppWidgets就是workerThread和UIthread都可能访问到的资源。在这段中做了两个备份,Runnable中用的备份。加了一个锁,只锁一小段代码,基本不会造成ANR。这就是一个原则,如果是workerThread和UIthread都可能访问到的资源,那么对这类资源加锁尽量短。看了代码大家应该就知道怎么搞好了。
/** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */
void unbindWorkspaceItemsOnMainThread() {
// Ensure that we don't use the same workspace items data structure on the main thread
// by making a copy of workspace items first.
final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();
final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();
synchronized (sBgLock) {
tmpWorkspaceItems.addAll(sBgWorkspaceItems);
tmpAppWidgets.addAll(sBgAppWidgets);
}
Runnable r = new Runnable() {
@Override
public void run() {
for (ItemInfo item : tmpWorkspaceItems) {
item.unbind();
}
for (ItemInfo item : tmpAppWidgets) {
item.unbind();
}
}
};
runOnMainThread(r);
}
项目中遇到一个ConcurrentModificationException异常,这种异常比较蛋疼,一般两个线程同时访问一个资源造成的,一个再改,一个再做别的,然后就不同步了。
Log数据中只给出一个点,不方便查询另一个问题点。这类必须解决的就是两个线程对同一个资源(我们这是一个HashMap)同步的问题,一个方式就是加锁解决,这是一个总方针。但是加锁如果加不好,就会造成UIthread的线程因为在锁那里等的时间比较长而造成ANR,当然这种情况不常见,因为你的超过5秒才能ANR,但是是有这个可能的,我们遇到了……
然后就是思考了两个方案,一个是做一个高优先级的线程(参考android线程优先级就能知道哪个合适,有俩都可以)来对UIthread里面对资源的访问提出来,这样不会ANR,但是项目大,地方多,这么干结构都得变,还有就是那种特别需要及时相应的地方(UI界面上的滑动动画啥的),担心这么做会有一定的延时。然后就放弃了,改动貌似有点大。
第二个方案就是做备份了,那备份给UIthread去使用。何时做、咋做备份又是个问题。然后就各种参考,这里不得不说,Android源码还是很碉堡的,最起码比我见过的一些大一点的项目代码要好。
给出一段代码,下面一段代码是桌面源码launcherModle里面的一段代码。
代码中sBgWorkspaceItems、sBgAppWidgets就是workerThread和UIthread都可能访问到的资源。在这段中做了两个备份,Runnable中用的备份。加了一个锁,只锁一小段代码,基本不会造成ANR。这就是一个原则,如果是workerThread和UIthread都可能访问到的资源,那么对这类资源加锁尽量短。看了代码大家应该就知道怎么搞好了。
/** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */
void unbindWorkspaceItemsOnMainThread() {
// Ensure that we don't use the same workspace items data structure on the main thread
// by making a copy of workspace items first.
final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();
final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();
synchronized (sBgLock) {
tmpWorkspaceItems.addAll(sBgWorkspaceItems);
tmpAppWidgets.addAll(sBgAppWidgets);
}
Runnable r = new Runnable() {
@Override
public void run() {
for (ItemInfo item : tmpWorkspaceItems) {
item.unbind();
}
for (ItemInfo item : tmpAppWidgets) {
item.unbind();
}
}
};
runOnMainThread(r);
}
相关文章推荐
- Android中workerthread与UIthread同时访问同一资源造成ConcurrentModificationException解决参考
- java.util.ConcurrentModificationException ,遍历集合并同时修改集合,并发造成的异常解决办法
- 问题描述: android.os.NetworkOnMainThreadException异常(不要在主线程访问网络资源)
- java 多线程同时操作ArrayList 出现ConcurrentModificationException 解决办法
- “android.os.NetworkOnMainThreadException”---关于Android4.0后无法将访问网络放入主线程中的解决办法
- java.util.ConcurrentModificationException 解决 Android
- java.util.ConcurrentModificationException异常参考解决方法
- java.util.ConcurrentModificationException 时的解决办法
- 使用CopyOnWriteArrayList来解决ArrayList上的ConcurrentModificationException
- Android 3.0 访问WebService 出现 android.os.NetworkOnMainThreadException异常
- java.util.ConcurrentModificationException 解决办法
- java.util.ConcurrentModificationException异常 解决方法
- ConcurrentModificationException 解决办法
- 遍历集合时删除元素,抛出java.util.ConcurrentModificationException的解决办法
- 解决ArrayList的java.util.ConcurrentModificationException
- 子线程更新UI会发生android.view.ViewRoot$CalledFromWrongThreadException异常的解决方法
- java.util.ConcurrentModificationException异常解决
- 子线程更新UI会发生android.view.ViewRoot$CalledFromWrongThreadException异常的解决方法
- Android 3.0 访问donet webService 出现 android.os.NetworkOnMainThreadException错误!
- 子线程更新UI会发生android.view.ViewRoot$CalledFromWrongThreadException异常的解决方法 .